android源码中不同设计模式的使用总结

设计模式之代理模式 - proxy

2017-02-24  本文已影响44人  ahking17

当你想控制外界对某个类的对象的直接访问时,可以使用代理模式.

定义

为其他类提供一种代理以控制外界对这个类的对象的访问.

核心作用

通过代理,控制对对象的访问;
可以详细控制访问某个类的方法,在调用这个方法前做前置处理, 调用这个方法后做后置处理.
AOP(Aspect Oriented Programming)面向切面编程的核心实现机制.

经典的使用模式:
  1. 代理类和被代理类实现同一个接口, 实现同一套API.
  2. 外界通过调用代理类的方法, 间接调用被代理类的方法.
  3. 在代理类中持有一个被代理类对象的引用, 真正的实现都是通过被代理类实现的.
代码中的使用

pulltorefresh项目

public interface ILoadingLayout {
    public void setLoadingDrawable(Drawable drawable);
}
//代理类
public class LoadingLayoutProxy implements ILoadingLayout {
    private final HashSet<LoadingLayout> mLoadingLayouts;

    @Override
    public void setLoadingDrawable(Drawable drawable) {
        for (LoadingLayout layout : mLoadingLayouts) {
            layout.setLoadingDrawable(drawable);
        }
    }
}
//被代理类
public abstract class LoadingLayout extends FrameLayout implements ILoadingLayout {

//真正的实现
    public final void setLoadingDrawable(Drawable imageDrawable) {
        // Set Drawable
        mHeaderImage.setImageDrawable(imageDrawable);
        mUseIntrinsicAnimation = (imageDrawable instanceof AnimationDrawable);

        // Now call the callback
        onLoadingDrawableSet(imageDrawable);
    }
}
//在pullToRefresh中创建这个代理类
public abstract class PullToRefreshBase<T extends View> {
    @Override
    public final ILoadingLayout getLoadingLayoutProxy() {
        return getLoadingLayoutProxy(true, true);
    }

    @Override
    public final ILoadingLayout getLoadingLayoutProxy(boolean includeStart, boolean includeEnd) {
        return createLoadingLayoutProxy(includeStart, includeEnd);
    }

    protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) {
        LoadingLayoutProxy proxy = new LoadingLayoutProxy();

        if (includeStart && mMode.showHeaderLoadingLayout()) {
            proxy.addLayout(mHeaderLayout);
        }
        if (includeEnd && mMode.showFooterLoadingLayout()) {
            proxy.addLayout(mFooterLayout);
        }

        return proxy;
    }
}
//外界的使用
//外界要想设置loadingLayout的图片时, 都要通过代理类LoadingLayoutProxy间接操作LoadingLayout.
//这样就做到了控制外界对实际LoadingLayout对象的访问.
public class MostAccessFragment {
    public PullToRefreshListView mPullToRefreshListView;

    @Override
    public void onThemeModeChanged(boolean isNightMode, int themeType, String themeId) {
            mPullToRefreshListView.getLoadingLayoutProxy().setLoadingDrawable(
                    getResources().getDrawable(R.drawable.info_from_pc_pull_down_rolling_night));
}
PullToRefreshListView extends PullToRefreshBase

这样设计的好处是, 当给LoadingLayout对象设置图片时, 外界并不需要去知道它使用的PullToRefreshListView中当前存在几个LoadingLayout对象, 遍历有几个LoadingLayout对象的工作由代理类LoadingLayoutProxy去实现, 遍历后依次去调用每一个LoadingLayout对象去设置图片.

使用代理模式就做到了:

控制外界对LoadingLayout对象的直接访问.

远程代理模式 - 使用基于aidl的binder通信

之前在pullToRefresh中使用的代理模式可以称为普通的代理模式, 还有另一个名词 - 远程代理模式, 指的是代理类的对象和被代理类的对象不在同一个进程空间.
典型的应用场景就是基于aidl的binder通信.

Intent service;
ServiceConnection connection = new ServiceConnection(){
    public void onServiceConnected(ComponetName name, IBinder service){
        ITestService testService = ITestService.stub.asInterface(service);
        //testService就是我们得到的远程代理对象
    }
    public void onServiceDisConnected(ComponentName name){
    }
}
context.bindService(service,connection);

testService就是我们得到的远程代理对象.
在客户端调用testService对象的方法, 真正的实现在服务端实现了ITestService.stub()接口的Binder mBinder对象.
显然, 客户端的testService远程代理对象和服务端的mBinder这个被代理的对象, 不在同一个进程空间.
这就是远程代理的概念.

------DONE.-----------

上一篇下一篇

猜你喜欢

热点阅读