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

简介: 参考《设计模式:可复用面向对象软件的基础 》4.7 Proxy 代理--对象结构型模式《Android源码设计模式解析与实战》第18章 编程好帮手--代理模式意图为其它对象提供一种代理以控制对这个对象的访问适用性在需要用比较通用和复杂的对象指针代替简单的指针的时候,使用Proxy模式。

参考

  • 《设计模式:可复用面向对象软件的基础 》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代理

待更

目录
相关文章
|
4月前
|
设计模式 缓存 监控
【设计模式系列笔记】代理模式
代理模式是一种结构型设计模式,它允许一个对象(代理对象)控制另一个对象的访问。代理对象通常充当客户端和实际对象之间的中介,用于对实际对象的访问进行控制、监控或其他目的。
68 1
|
4月前
|
设计模式 缓存 安全
小谈设计模式(8)—代理模式
小谈设计模式(8)—代理模式
|
5天前
|
设计模式 缓存 安全
设计模式——代理模式
静态代理、JDK动态代理、Cglib 代理
设计模式——代理模式
|
4月前
|
设计模式 Java
Java一分钟之-设计模式:装饰器模式与代理模式
【5月更文挑战第17天】本文探讨了装饰器模式和代理模式,两者都是在不改变原有对象基础上添加新功能。装饰器模式用于动态扩展对象功能,但过度使用可能导致类数量过多;代理模式用于控制对象访问,可能引入额外性能开销。文中通过 Java 代码示例展示了两种模式的实现。理解并恰当运用这些模式能提升代码的可扩展性和可维护性。
49 1
|
4月前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
1月前
|
设计模式 缓存 Java
【十一】设计模式~~~结构型模式~~~代理模式(Java)
文章详细介绍了代理模式(Proxy Pattern),这是一种对象结构型模式,用于给对象提供一个代理以控制对它的访问。文中阐述了代理模式的动机、定义、结构、优点、缺点和适用环境,并探讨了远程代理、虚拟代理、保护代理等不同代理形式。通过一个商务信息查询系统的实例,展示了如何使用代理模式来增加身份验证和日志记录功能,同时保持客户端代码的无差别对待。此外,还讨论了代理模式在分布式技术和Spring AOP中的应用,以及动态代理的概念。
【十一】设计模式~~~结构型模式~~~代理模式(Java)
|
1月前
|
设计模式
设计模式的基础问题之代理模式在工作中的问题如何解决
设计模式的基础问题之代理模式在工作中的问题如何解决
|
2月前
|
设计模式 算法 Go
iLogtail设计模式问题之代理模式在iLogtail中是如何应用的
iLogtail设计模式问题之代理模式在iLogtail中是如何应用的
|
2月前
|
设计模式 缓存 JavaScript
js设计模式【详解】—— 代理模式
js设计模式【详解】—— 代理模式
23 0
|
3月前
|
设计模式 监控 安全
设计模式之代理模式(Java)
设计模式之代理模式(Java)