Android设计模式之代理模式

代理模式(Proxy Pattern)也称为委托模式。

代理模式的定义

为其它对象提供一种代理以控制对这个对象的访问。

代理模式的使用场景

当无法或者不想直接访问某个对象或者访问某个对象存在困难时,可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,委托对象与代理对象需要实现相同的接口。

代理模式的UML类图

角色介绍:

Subject:抽象主题类

该类的主要职责是声明真实主题与代理的共同接口方法,该类既可以是一个抽象类也可以是一个接口。

RealSubject:真实主题类

该类也被称为被委托类或被代理类,该类定义了代理所表示的真实对象,由其执行具体的业务逻辑方法,而客户端则通过代理类间接调用真实主题类中定义的方法。

ProxySubject:代理类

该类也称为委托类或代理类,该类持有一个对真实主题类的引用,在其所实现的接口方法中调用真实主题类中相应的接口方法执行,以此起到代理的作用。

代理模式大概分为两部分:一是静态代理,二是动态代理;静态代理代码如Demo所示,代理者的代码由程序员自己或者通过一些自动化工具生成固定的代码再对其进行编译,也就是在我们的代码运行前 代理类的 class编译文件 就已经存在。

而动态代理和静态代理相反,通过反射机制 动态生成代理者的对象,也就是说我们在code阶段不需要知道代理谁,代理谁将会在执行阶段决定。而Java给我们提供了一个便捷的动态代理接口InvocationHandler,实现该接口需要重写其调用方法invoke。

public class DynamicProxy implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return null;
    }
}

在这里,通过invoke方法调用具体的被代理方法,也就是真实的方法。

public class DynamicProxy implements InvocationHandler {

    private Object object;

    public DynamicProxy(Object object) {
        this.object = object;
    }
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        
        //调用被代理对象的方法
        Object result = method.invoke(object, args);
        return result;
    }
}

动态代理通过一个代理类来代理n个被代理类,其实质是对代理者与被代理者进行解耦,使两者没有直接的耦合关系。相对而言静态代理则只能给定接口下的实现类做代理,如果接口不同则需要重新定义不同的代理类,较为复杂。但是静态代理更加符合面向对象原则。

静态代理和动态代理是从Code方面区分代理模式的两种方式,我们也可以从其适用范围来区分不同类型的代理模式。

1.远程代理(Remote Proxy):为某个对象在不同的内存地址空间 提供局部代理。使系统可以将Server部分的实现隐藏,以便Client可以不必考虑Server的存在。

2.虚拟代理(Virtual Proxy):使用一个代理对象表示一个十分耗资源的对象并在正真需要的时候才创建。

3.保护代理(Production Proxy):使用代理控制对原始对象的访问。该类型的代理常被用于原始对象有不同访问权限的情况。

4.智能引用(Smart Reference):在访问原始对象时执行一些自己的附加操作并对指向原始对象的引用计数。

需要注意的是,静态和动态代理都可以应用于上述4钟情形。

 

代理模式简单Demo

D:\Users\user\AndroidStudioProjects\ProxyPatternDemo\app\src\main\java\proxy_pattern\gome\com\proxypatterndemo\Subject.java

public abstract class Subject {

    public abstract void visit();
}


D:\Users\user\AndroidStudioProjects\ProxyPatternDemo\app\src\main\java\proxy_pattern\gome\com\proxypatterndemo\RealSubject.java

public class RealSubject extends Subject {
    @Override
    public void visit() {
        Log.v(TAG, "Real subject!");
    }
}

D:\Users\user\AndroidStudioProjects\ProxyPatternDemo\app\src\main\java\proxy_pattern\gome\com\proxypatterndemo\ProxySubject.java


public class ProxySubject extends Subject {
    private RealSubject mSubject;//持有真实主题的引用

    public ProxySubject(RealSubject subject) {
        this.mSubject = subject;
    }

    @Override
    public void visit() {
        //通过真实主题引用的对象调用真实主题中的逻辑方法
        mSubject.visit();
    }
}


D:\Users\user\AndroidStudioProjects\ProxyPatternDemo\app\src\main\java\proxy_pattern\gome\com\proxypatterndemo\MainActivity.java

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "ZY_PROXY_PATTERN";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //构造一个真实主题对象
        RealSubject real = new RealSubject();
        //通过真实主题对象构建一个代理对象
        ProxySubject proxy = new ProxySubject(real);

        //调用代理的相关方法
        proxy.visit();
    }
}

Log分析:

V/ZY_PROXY_PATTERN: Real subject!

 

在java的动态代理机制中,有两个重要的类或接口,一个是 InvocationHandler(Interface)、另一个则是 Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的。

首先我们先来看看java的API帮助文档是怎么样对这两个类进行描述的:

 

每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用。我们来看看InvocationHandler这个接口的唯一一个方法 invoke 方法:

 

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

 

我们看到这个方法一共接受三个参数,那么这三个参数分别代表什么呢?

 

Object invoke(Object proxy, Method method, Object[] args) throws Throwable

 

proxy:  指代我们所代理的那个真实对象

method:  指代的是我们所要调用真实对象的某个方法的Method对象

args:  指代的是调用真实对象某个方法时接受的参数

 

Android源码中代理模式实现

WindowManager只是一个代理,实际的管理功能是通过WindowManagerGlobal实现的。

Android源码中代理模式的实现,比如源码里面的ActivityManagerProxy代理类,其具体代理的是ActivityManagerNative的子类ActivityManagerService,ActivityManagerService在本书中其他章节略有介绍,这里不再多说,主要来看看ActivityManagerProxy这个类。

上面的IActivityManager这个接口类就相当于代理模式中的抽象主题,真正实现主题的是ActivityManagerService类。

 

public class ActivityManagerService extends IActivityManager.Stub
        implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
        ... ...
}


@SystemService(Context.ACTIVITY_SERVICE)
public class ActivityManager {

}

以ActivityManager的getAppTasks为例:


 /**
     * Get the list of tasks associated with the calling application.
     *
     * @return The list of tasks associated with the application making this call.
     * @throws SecurityException
     */
    public List<ActivityManager.AppTask> getAppTasks() {
        ArrayList<AppTask> tasks = new ArrayList<AppTask>();
        List<IBinder> appTasks;
        try {
            appTasks = getService().getAppTasks(mContext.getPackageName());
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
        int numAppTasks = appTasks.size();
        for (int i = 0; i < numAppTasks; i++) {
            tasks.add(new AppTask(IAppTask.Stub.asInterface(appTasks.get(i))));
        }
        return tasks;
    }


  /**
     * @hide
     */
    public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

//Android framework中大多使用静态内部类的方式实现单例。
private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };





package android.util;

/**
 * Singleton helper class for lazily initialization.
 *
用于延迟初始化的Singleton helper类。
 * Modeled after frameworks/base/include/utils/Singleton.h
 *
 * @hide
 */
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

通过上述代码可以发现:只是简单调用了ActivityManager 的 getService() 方法获取到一个IActivityManager类型的对象。然后通过该对象再调用其getAppTasks 方法。注意,这里结合代理模式理解。而ActivityManager 的getService()方法只是单纯的返回了。

getService()方法的操作是什么呢?

 public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }


private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);("activity" -> Context.ACTIVITY_SERVICE)
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

上述代码通过静态内部类的方式构建了一个Singleton<IActivityManager> 类型的IActivityManagerSingleton 对象, 其中通过ServiceManager.getService(Context.ACTIVITY_SERVICE)方法获取一个系统级的Service,而这个Service实质上就是ActivityManagerService,这里也就完成了创建了一个ActivityManagerService的Client代理对象IActivityManager实例

#ActivityManagerService
 @Override
    public List<IBinder> getAppTasks(String callingPackage) {
        int callingUid = Binder.getCallingUid();
        long ident = Binder.clearCallingIdentity();

        synchronized(this) {
            ArrayList<IBinder> list = new ArrayList<IBinder>();
            try {
                if (DEBUG_ALL) Slog.v(TAG, "getAppTasks");

                final int N = mRecentTasks.size();
                for (int i = 0; i < N; i++) {
                    TaskRecord tr = mRecentTasks.get(i);
                    // Skip tasks that do not match the caller.  We don't need to verify
                    // callingPackage, because we are also limiting to callingUid and know
                    // that will limit to the correct security sandbox.
                    if (tr.effectiveUid != callingUid) {
                        continue;
                    }
                    Intent intent = tr.getBaseIntent();
                    if (intent == null ||
                            !callingPackage.equals(intent.getComponent().getPackageName())) {
                        continue;
                    }
                    ActivityManager.RecentTaskInfo taskInfo =
                            createRecentTaskInfoFromTaskRecord(tr);
                    AppTaskImpl taskImpl = new AppTaskImpl(taskInfo.persistentId, callingUid);
                    list.add(taskImpl.asBinder());
                }
            } finally {
                Binder.restoreCallingIdentity(ident);
            }
            return list;
        }
    }

参考《Android源码设计模式》

猜你喜欢

转载自blog.csdn.net/zhangying1994/article/details/85339089
今日推荐