《Android源码设计模式解析与实战》读书笔记(十八)_唯鹿的博客-程序员秘密

技术标签: 读书笔记  android  《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.缺点

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

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_17766199/article/details/50492805

智能推荐

【UiPath2022+C#】UiPath控制流程概述_uipath输入对话框_会敲键盘的肘子的博客-程序员秘密

这大概是最详细的UiPath使用文档,环境:UiPath Studio Community 2022.4.3/Windows/C#,网上的文档和教程基本都是VB的,本文基于C#学习UiPath。

jvm内存模型_jvm内存模型 jwxra_a5302091的博客-程序员秘密

一、回顾JVM内存模型二、PermGen(永久代)上一篇文章没有提到永久代,这里详细介绍下。绝大部分 Java 程序员应该都见过 "java.lang.OutOfMemoryError: PermGen space "这个异常。这里的 “PermGen space”其实指的就是方法区。不过方法区和“PermGen space”又有着本质的区别。前者是 JVM 的规范,而后者则是 JV...

古老CPU启示录-第一款单芯片微处理器8080_碎碎思的博客-程序员秘密

从今天来看:“该芯片是二十世纪最重要的产品。8080及其后续的芯片和其它公司生产的竞争芯片,对世界产生了深远的影响,给人类社会带来了翻天覆地的变化。”,那么什么芯片具有如此大的魔力?那就是...

QT虚拟键盘(QWidget)的实现_qt 嵌入式虚拟键盘_我是东山啊#的博客-程序员秘密

*QT虚拟键盘的实现:**在QApplication a(argc, argv);之前加上qputenv(“QT_IM_MODULE”, QByteArray(“qtvirtualkeyboard”));即可实现简易的虚拟键盘(qt自带的):main.cpp#include "mainwindow.h"#include <QApplication>#include"lineedit.h"#include <QtWidgets>#include"QDebug...

Microsoft Word教程:如何在 Word 中创建文档、添加和编辑文本?_word文档怎么做_Mac柠檬的博客-程序员秘密

欢迎观看 Microsoft Word 教程,小编带大家学习 Microsoft Word 的使用技巧,了解如何在 Word 中创建文档、添加和编辑文本。

设置更改root密码、连接MySQL、MySQL常用的命令_rain_yunlx的博客-程序员秘密

一、设置更改root密码1. 先将mysql目录加入环境变量中export PATH=$PATH:/usr/local/mysql/bin/2.再将命令写入到配置文件中,永久生效vim /etc/profile 在文件中添加如下的内容:export PATH=$PATH:/usr/local/mysql/bin/3. 设置mysql 密码mysqladmin -uroot password 'te...

随便推点

关于pycharm中使用anaconda 的python环境中多版本切换使用的总结_Jesse的开发记事本的博客-程序员秘密

一般切换开发环境版本都是在file---setting里面去设置选择你安装的开发版本如下图:但是,你切换了这个开发环境版本,只是针对你的.py文件的运行环境来的,你要安装其它的包到你切换的python环境的时候,你就要用到terminal,可是terminal 默认是跟随系统配置的环境变量的python环境来的。如果你要用其它版本就不行了,这个时候我们需要切换版本:命令行输入以下命令会...

matlab转子位置检测,永磁同步电机的转子初始位置检测_Gullet的博客-程序员秘密

1. 引言永磁同步电机(PMSM)因其具有高性能、工作密度高、控制特性优良和可靠性高等特点,在军事与民用领域都取得了广泛的应用。在其控制过程中,无论是直接转矩控制还是矢量控制,都对电机转子的初始位置确定有极高的要求。传统的永磁同步电机转子位置检测主要是通过机械式位置传感器来实现的,这些传感器包括测速发电机、旋转变压器或光电编码器等。但在高温、超时、高粉尘等环境工作时,它们的可靠性将大大降低 [1]...

java break 跳出多层for循环_别抢我蓝buff的博客-程序员秘密

public static void main(String[] args){ tag2: for(int i=0;i<5;i++){ tag1: for(int k=0;k<5;k++){ System.out.println(k); if(k==1){ break tag2;

react +axios 后端使用springboot进行跨域请求时数据丢失问题_qq_31685413的博客-程序员秘密

虽然目前也不知道为什么但是也查了好久的治疗。数据在处理之前需要用qs进行格式化如下return axios.post(url, qs.stringify(data), { headers: { 'Content-Type': 'application/x-www-form-urlencod...

【OpenCV学习笔记1】OpenCV 编程简介[轉]_weixin_30879833的博客-程序员秘密

OpenCV 编程简介(矩阵/图像/视频的基本读写操作)Introduction to programming with OpenCVOpenCV编程简介作者: Gady AgamDepartment of Computer ScienceJanuary 27, 2006Illinois Institute of TechnologyURL: http://www....

剑指offer——数组中的逆序对(复习归并排序)_qqqqq1993qqqqq的博客-程序员秘密

题目描述 在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007 输入描述: 题目保证输入的数组中没有的相同的数字 数据范围: 对于%50的数据,size<=10^4 对于%75的数据,size<=10^5 对于%