Android中的设计模式之代理模式

参考

  • 《设计模式:可复用面向对象软件的基础 》4.7 Proxy 代理--对象结构型模式
  • 《Android源码设计模式解析与实战》第18章 编程好帮手--代理模式

意图

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

适用性

在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。

  • 远程代理 为一个对象在不同的地址空间提供局部代表。这一点Android Binde实现跨进程通信很典型
  • 虚代理 根据需要创建开销很大的对象。
  • 保护代理 控制对原始对象的访问。保护代理用于对象应该有不同的访问权限的时候。
  • 智能指引 取代了简单的指针,它在访问对象时执行一些附加操作。
    • 对指向实际对象的引用计数,这样当该对象没有引用时,可以自动释放它,难道Java就是这个原理?
    • 当第一次引用一个持久对象时,将它装入内存
    • 在访问一个实际对象前,检查是否已经锁定了它,以确保其它对象不能改变它。

结构

代理模式结构

角色

  • Client

客户类,即使用代理类的类型

  • Subject 抽象主题类 抽象了代理行为

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

  • RealSubject 实现抽象主题的真实主题类

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

  • Proxy 委托类或代理类
    • 持有对真实主题类的引用,可以访问真实实体
    • 提供一个与Subject的接口相同的接口,这样代理就可以用来替代实体
    • 控制对实体的存取,并可能负责创建或者删除它
    • 相对与实体的其它附加功能依赖于代理的类型

协作

代理根据其种类,在适当的时候向RealSubject转发请求

代理执行流程

效果

Proxy模式在访问对象时引入了一定程度的间接性。根据代理的类型,附件的间接性有多种用途

  • Remote Proxy可以隐藏一个对象存在不同地址空间的事实。
  • Virtual Proxy 可以进行优化,例如根据要求创建对象。
  • Protection Proxies和Smart Reference都允许在访问一个对象时有一些附加的内务处理

应用例子1 小明打官司

描述

小明被老板拖欠工资,小明选择了走发法律途径解决该纠纷。所以小明请律师作为自己的诉讼代理人。

结构

结构

java实现

/**
* 
* @author newtrekwang
* @desc 代理接口 
* 2017年3月4日
*/
public interface ILawSuit {
//  提交申请
       void submit();
//      进行举证
       void burden();
//      开始辩护
       void defend();
//      诉讼完成
       void finish();
}

/**
* 
* @author newtrekwang
* @desc 被代理者小明 
* 2017年3月4日
*/
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("诉讼成功!判决老板即日起七天内结算工资!");
       
   }

}


/**
* 
* @author newtrekwang
* @desc  代理律师
* 2017年3月4日
*/
public class Lawyer implements ILawSuit {
//  持有一个具体被代理者的引用
   private ILawSuit mLawSuit;
   
    public Lawyer(ILawSuit iLawSuit) {
        this.mLawSuit=iLawSuit;
    }

   @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 static void main(String[] args) {
        ILawSuit xiaoMin=new XiaoMin();
        Lawyer lawyer=new Lawyer(xiaoMin);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
    

结果

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

java的静态代理和动态代理

  • 静态代理:静态代理如上述代码一样,代理者的代码由程序员自己或通过一些自动化工具生成固定的代码再对其进行编译,也就是说我们的代码运行前代理类的class编译文件就已存在;
  • 动态代理:与静态代理相反,通过反射机制动态地生成代理者的对象,也就是说我们在code阶段不知道要代理谁,代理谁我们将会在执行阶段决定。而Java也给我们提供了一个便捷的动态代理接口InvocationHandler,实现该接口需要重写其调用方法invoke.
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxy  implements InvocationHandler{
    private Object obj;//被代理的类引用
    
     public DynamicProxy(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;
    }
}

使用

    public static void main(String[] args) {
//      构造一个小明
        ILawSuit xiaoMin=new XiaoMin();
//      构造一个动态代理
        DynamicProxy dynamicProxy=new DynamicProxy(xiaoMin);
//      获取被代理类小明的ClassLoader
        ClassLoader loader=xiaoMin.getClass().getClassLoader();
//      动态构造一个代理者律师
        ILawSuit lawyer=(ILawSuit) Proxy.newProxyInstance(loader, new Class[]{ILawSuit.class}, dynamicProxy);
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }

结果

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

应用例子2 嵌入图形对象的文档编辑器

描述

对一个对象进行访问控制的一个原因时为了只有在我们真正需要这个对象时才对它进行创建和初始化。考虑一个可以在文档中嵌入图形对象的文档编辑器,有些图形对象(大图)的创建开销很大,但是打开文档必须很迅速,因此我们在打开文档时应避免一次性创建所有开销很大的对象,因为并非所有这些对象在文档中都同时可见,所以也没有必要同时创建这些对象。

这一限制条件意味着,对于每一个开销很大的对象,应该根据需要进行创建。问题的解决方案就是使用另一个对象,即图像Proxy,代替那个真正的图像。Proxy可以代替一个图像对象,并且在需要时负责实例化这个图像对象。

结构

结构

源码就略了

应用例子3 Retrofit 中的动态代理

待更

应用例子4 Android Service代理

待更

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 3,232评论 2 10
  • 设计模式汇总 一、基础知识 1. 设计模式概述 定义:设计模式(Design Pattern)是一套被反复使用、多...
    MinoyJet阅读 3,933评论 1 15
  • “你有没有爱过一个人,或者说你有没有恨过一个人?”“没有!”我很随意地将手里的烟掐灭,然后抛弃,看着它在空中落地形...
    文巾阅读 122评论 0 2
  • 一、财富篇 1、省一分钱净赚两分钱,几年后你会拥有一堆钞票。 2、有计划开支好的家可以用一百个家庭。多挣少花是致富...
    小草草小阅读 457评论 0 0