《Android源码设计模式解析与实战》读书笔记(十八)

第十八章、代理模式

代理模式也称委托模式,是结构型设计模式之一。是应用广泛的模式之一。

1.定义

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

2.使用场景

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

3.UML类图

(1)Subject:抽象主题类,声明真实主题与共同接口方法,该类可以是抽象类或接口。

(2)RealSubject:真实主题类(被委托类),尤其执行具体的业务逻辑方法。

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

4.简单实现

书中例子:以小民诉讼的流程举例。那么需要代理律师代理,诉讼简单流程:提交申请–>进行举证–>开始辩护–>诉讼完成。

诉讼接口类:

public interface ILawsuit {

    /**
     * 提交申请
     */
    void submit();

    /**
     * 进行举证
     */
    void burden();

    /**
     * 开始辩护
     */
    void defend();

    /**
     * 诉讼完成
     */
    void finish();
}

具体诉讼人小民:

public class XiaoMin implements ILawsuit{

    @Override
    public void submit() {
        //小民申请仲裁
        System.out.println("老板年底拖欠工资,特此申请仲裁!");
    }

    @Override
    public void burden() {
        //小民提交证据
        System.out.println("这是合同书和过去一年的银行工资流水!");
    }

    @Override
    public void defend() {
        //铁证如山
        System.out.println("证据确凿,不需要再说什么!");
    }

    @Override
    public void finish() {
        //结果
        System.out.println("诉讼成功,判决老板即日起七天内结算工资!");
    }

}

代理律师:

public class Lawyer implements ILawsuit{

    private ILawsuit mLawsuit; //持有一个具体被代理者的引用

    public Lawyer(ILawsuit lawsuit) {
        this.mLawsuit = lawsuit;
    }

    @Override
    public void submit() {
        mLawsuit.submit();
    }

    @Override
    public void burden() {
        mLawsuit.burden();
    }

    @Override
    public void defend() {
        mLawsuit.defend();
    }

    @Override
    public void finish() {
        mLawsuit.finish();
    }

}

开始仲裁:

public class Client {
    public static void main(String[] args) {
        //构造出诉讼人小民
        ILawsuit xiaomin = new XiaoMin();

        //构造一个代理律师,并将小民传递进去
        ILawsuit lawyer = new Lawyer(xiaomin);

        //律师提交申请
        lawyer.submit();

        //律师进行举证
        lawyer.burden();

        //律师代小民辩护
        lawyer.defend();

        //完成诉讼
        lawyer.finish();
    }
}

结果:

老板年底拖欠工资,特此申请仲裁!
这是合同书和过去一年的银行工资流水!
证据确凿,不需要再说什么!
诉讼成功,判决老板即日起七天内结算工资!

同样我们也可以代理其他人,只需要实现ILawsuit即可。上面的代理模式也叫静态代理,也就是在代码运行前代理类的class文件就已经存在。那么相反,当然也会有动态代理,下面用动态代理实现上述例子:

Java提供了一个便捷的动态代理接口InvocationHandler,我们来实现它:

public class DynamicPorxy implements InvocationHandler{

    private Object obj; //被代理类的引用

    public DynamicPorxy(Object obj) {
        this.obj = obj;
    }

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

}

这里我们通过invoke方法来调用具体的被代理方法。

修改后的Client类:

public class Client {
    public static void main(String[] args) {
        //构造出诉讼人小民
        ILawsuit xiaomin = new XiaoMin();

        //1.静态代理
        //构造一个代理律师,并将小民传递进去
        //ILawsuit lawyer = new Lawyer(xiaomin);

        //--------------------------------------
        //2.动态代理
        //构造一个动态代理
        DynamicPorxy proxy = new DynamicPorxy(xiaomin);

        //获取被代理类小民的ClassLoader
        ClassLoader loader = xiaomin.getClass().getClassLoader();

        //动态构造一个代理者律师
        ILawsuit lawyer = (ILawsuit) Proxy.newProxyInstance(loader, new Class[]{ ILawsuit.class }, proxy);

        //律师提交申请
        lawyer.submit();

        //律师进行举证
        lawyer.burden();

        //律师代小民辩护
        lawyer.defend();

        //完成诉讼
        lawyer.finish();
    }
}

结果不变,由此可以看出动态代理通过一个代理类来处理N多个被代理类,其实质是对代理者与被代理者解耦。相对而言静态代理则只能为给定接口下的实现类做代理,如果接口不同那么就需要重新定义不同的代理类,较为复杂,但是静态代理更符合面向对象原则。具体使用哪种方式,根据个人喜好。

5.Android源码中的代理模式实现

1.ActivityManagerProxy代理类

ActivityManager是Android中管理和维护Activity的相关信息的类,为了隔离它与ActivityManagerService,有效降低二者的耦合,在这中间使用了ActivityManagerProxy代理类,所有对ActivityManagerService的访问都转换成对代理类的访问,这样ActivityManager就与ActivityManagerService解耦了。

6.总结

1.优点

(1)对代理者与被代理者进行解耦。

(2)代理对象在客户端和目标对象之间起到一个中介的作用,这样可以起到对目标对象的保护。

2.缺点

基本没有缺点,真要说缺点就是设计模式的通病:对类的增加。

时间: 2024-10-12 16:07:56

《Android源码设计模式解析与实战》读书笔记(十八)的相关文章

《Android源码设计模式解析与实战》读书笔记(十三)

第十三章.备忘录模式 备忘录模式是一种行为模式,该模式用于保存对象当前的状态,并且在之后可以再次恢复到此状态,有点像是我们平常说的"后悔药". 1.定义 在不破坏封闭的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态,这样,以后就可将该对象恢复到原先保存的状态. 2.使用场景 (1)需要保存一个对象在某一个时刻的状态或部分状态. (2)如果用一个接口来让其他对象得到这些状态,将会暴露对象的实现细节并破坏对象的封装性,一个对象不希望外界直接访问其内部状态,通过中间对象可以间接访

《Android源码设计模式解析与实战》读书笔记(二十二)

第二十二章.享元模式 享元模式是结构型设计模式之一,是对对象池的一种实现.就像它的名字一样,共享对象,避免重复的创建.我们常用的String 就是使用了共享模式,所以String类型的对象创建后就不可改变,如果当两个String对象所包含的内容相同时,JVM只创建一个String对象对应这两个不同的对象引用. 1.定义 采用一个共享来避免大量拥有相同内容对象的开销.使用享元模式可有效支持大量的细粒度对象. 2.使用场景 (1)系统中存在大量的相似对象. (2)细粒度的对象都具备较接近的外部状态,

《Android源码设计模式解析与实战》读书笔记(十四)

第十四章.迭代器模式 迭代器模式,又叫做游标模式,是行为型设计模式之一.我们知道对容器对象的访问必然会涉及遍历算法,我们可以将遍历的方法封装在容器中,或者不提供遍历方法,让使用容器的人自己去实现去吧.这两种情况好像都能够解决问题. 然而在前一种情况,容器承受了过多的功能,它不仅要负责自己"容器"内的元素维护(添加.删除等等),而且还要提供遍历自身的接口:而且由于遍历状态保存的问题,不能对同一个容器对象同时进行多个遍历.第二种方式倒是省事,却又将容器的内部细节暴露无遗. 正因于此,迭代器

《Android源码设计模式解析与实战》读书笔记(十一)

第十一章.命令模式 命令模式是行为型模式之一.总体来说并不难理解,只是比较繁琐,他会将简单的调用关系解耦成多个部分,增加类的复杂度,但是即便如此,命令模式的结构依然清晰. 1.定义 将一个请求封装成一个对象,从而让用户使用不同的请求把客户端参数化:对请求排队或者记录请求日志,以及支持可撤销的操作. 2.使用场景 (1)需要抽出待执行的动作,然后以参数的形式提供出来. (2)在不同的时刻指定.排列和执行请求.一个命令对象可以有与初始请求无关的生存期. (3)需要支持操作取消. (4)支持修改日志功

《Android源码设计模式解析与实战》读书笔记(二十一)

第二十一章.装饰模式 装饰模式也称为包装模式,是结构型设计模式之一.装饰模式是一种用于替代继承技术的一种方案. 1.定义 动态的给一个对象添加一些额外的职责.就增加功能来说,装饰模式相比生成子类更为灵活. 2.使用场景 (1)需要透明且动态地扩展类的功能时.且在不影响其他对象的情况下. (2)当不能采用继承对系统进行扩展时可以使用装饰模式.比如final类. 3.UML类图 (1)Component:抽象组件.可以是一个接口或抽象类,其充当的就是被装饰的原始对象. (2)ConcreteComp

《Android源码设计模式解析与实战》读书笔记(十二)

第十二章.观察者模式 观察者模式是一个使用率非常高的模式,它最常用在GUI系统.订阅–发布系统.因为这个模式的一个重要作用就是解耦,将被观察者和观察者解耦,使得它们之间的依赖性更小,甚至做到毫无依赖.比如安卓的开源项目EventBus.Otto.AndroidEventBus等事件总线类的和RxJava响应式编程其核心都是使用观察者模式. 1.定义 观察者模式是一种行为类模式,它定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 2.使用场景

《Android源码设计模式解析与实战》读书笔记(二十四)

第二十四章.桥接模式 桥接模式也称为桥梁模式,是结构型设计模式之一.桥接模式中体现了"单一职责原则"."开闭原则"."里氏替换原则"."依赖倒置原则"等.同时它也是很实用的一种模式. 1.定义 将抽象部分与现实部分分离,使它们都可以独立地进行变化. 2.使用场景 (1)如果一个系统需要在构建的抽象化角色和具体角色之间增加更多的灵活性,避免在两个层次之间建立静态的继承联系. (2)对于那些不希望使用继承或因为多层次继承导致系统类

《Android源码设计模式解析与实战》读书笔记(十)

第十章.解释器模式 解释器模式是一种用的比较少的行为型模式,其提供了一种解释语言的语法或表达式的方式.但是它的使用场景确实很广泛,只是因为我们自己很少回去构造一个语言的文法,所以使用较少. 1.定义 给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子.(其中语言就是我们需要解释的对象,文法就是这个语言的规律,解释器就是翻译机,通过文法来翻译语言.) 2.使用场景 1.如果某个简单的语言需要解释执行而且可以将该语言中的语句表示为一个抽象的语法树时可以考虑使

《Android源码设计模式解析与实战》读书笔记(八)

第八章.状态模式 1.定义 状态模式中的行为是由状态来决定,不同的状态下有不同的行为.当一个对象的内在状态改变时允许改变其行为,这个对象看起来像是改变了其类. 2.使用场景 1.一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变它的行为. 2.代码中包含大量与对象状态有关的条件语句,例如,一个操作中含有大量的多分支语句,且这些分支依赖于该对象的状态. 3.简单实现 实现效果:首先将电视的状态分为开机与关机状态,开机时可以通过遥控器实现频道切换和调节音量,但是关机时,这些操作都会失效.