关闭

Android设计模式之代理模式(Proxy Pattern)

标签: android设计模式代理模式AMS
1562人阅读 评论(0) 收藏 举报
分类:

代理模式介绍

代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种,代理模式在各类开发中运用的相当广泛,不论是j2ee,android还是ios,都能看到它的身影,所以说设计模式无处不在。

代理模式的定义:

为其他对象提供一种代理以控制这个对象的访问。通俗一点:找别人做你想做但是做不了的事情。

代理模式的UML类图,如图:

这里写图片描述

角色介绍:

   (1) 抽象主题(Subject):定义了真实主题(RealSubject)和代理  (Proxy)的公共接口,这样就在任何时候使用真实主题(RealSubject)的地方使用代理(Proxy)。
  (2) 代理(Proxy):保存一个引用使得代理可以直接访问真实主题,并提供一个与Subject的接口相同的接口,这样代理就可以代替真实主题。
  (3) 真实主题(RealSubject):定义Proxy所代表的真实主题。
  (4) 客户类(Client):即使用代理类的类型。

代理模式的简单实现

背景描述

在生活中代理模式也是经常存在,比如2011年老罗针对西门子冰箱门关不严,进行维权。假设找到了律师进行维权,那么这种方式就是代理模式,当然老罗可以自己打官司,也可以自己打官司,有相同的地方,也有不同的地方。

相同的地方在于:
1、 诉讼申请:都需要提交原告的资料,如姓名、年龄、事情缘由、想达到的目的。
2、 诉讼取证:都需要经过法院的取证调查,开庭争辩等过程。
3、 诉讼完成:最后拿到审判结果。

不同地方在于:
1、 节省时间:老罗省事了,让专业的人做专业的事,不需要自己再去了解法院那一套繁琐复杂的流程。
2、 成功性概率:把握更大了。

通过上面的例子,我们注意到代理模式有几个重点。
1、 被代理的角色(老罗)
2、 代理角色(律师)
3、 协议(不管是代理和被代理谁去做,都需要做的事情,抽象出来就是协议)

具体代码实现

定义诉讼协议接口ILawProtocol.java:

/**
 *诉讼协议接口:规定诉讼的一般流程
 */
public interface ILawProtocol {
    void submit();//提交申请
    void burden();//进行举证
    void defend();//开始辩护
    void finish();//诉讼完成
}

定义具体的诉讼人LaoLuo .java:

/*
 * 具体的诉讼人:继承诉讼接口
 */
public class LaoLuo implements ILawProtocol{

    @Override
    public void submit() {
        // TODO Auto-generated method stub
        System.out.println("申请:西门子冰箱质量缺陷,特此申请民事仲裁!");
    }

    @Override
    public void burden() {
        // TODO Auto-generated method stub
        System.out.println("证据:这是购买冰箱的发票,以及冰箱质量问题的视频!");
    }

    @Override
    public void defend() {
        // TODO Auto-generated method stub
        System.out.println("辩护:我们证据确凿,必须得到应该的赔偿!");
    }

    @Override
    public void finish() {
        // TODO Auto-generated method stub
        System.out.println("诉讼完成:判决西门子北京分公司在七日之内退还老罗购买冰箱的成本!");
    }
}

定义代理律师类Lawyer .java

/*
 * 代理律师类:继承诉讼接口
 */
public class Lawyer implements ILawProtocol{

    private ILawProtocol mILawSuit;//关联一个诉讼人
    public Lawyer(ILawProtocol mILawSuit) {
        super();
        this.mILawSuit = mILawSuit;
    }

    @Override
    public void submit() {
        // TODO Auto-generated method stub
        mILawSuit.submit();//提交申请
    }

    @Override
    public void burden() {
        // TODO Auto-generated method stub
        mILawSuit.burden();//进行举证
    }

    @Override
    public void defend() {
        // TODO Auto-generated method stub
        mILawSuit.defend();//开始辩护
    }

    @Override
    public void finish() {
        // TODO Auto-generated method stub
        mILawSuit.finish();//诉讼完成
    }

}

开庭审理测试Test.java:

import java.lang.reflect.Proxy;
public class Test {
    public static void main(String[] args) {
        //构造一个具体要诉讼的人:老罗
        ILawProtocol laoluo=new LaoLuo();
        /**使用静态代理**/
        //构造一个代理律师,并将老罗作为构造参数传进去
        ILawProtocol lawyer=new Lawyer(laoluo);
        //执行诉讼人的相关行为
        lawyer.submit();
        lawyer.burden();
        lawyer.defend();
        lawyer.finish();
    }
}

打印结果如下:

诉讼申请:西门子冰箱质量缺陷,特此申请民事仲裁!
诉讼证据:这是购买冰箱的发票,以及冰箱质量问题的视频!
诉讼辩护:我们证据确凿,必须得到应该的赔偿!
诉讼完成:判决西门子北京分公司在七日之内退还老罗购买冰箱的成本!

上文使用的是静态代理,但是静态代理后期扩展和维护比较困难,因为代码写的太死,没有可替换的余地;针对代码写得死能想到什么解决办法?对,就是反射。使用反射可以很到的解决决定加载哪个代理类的问题,避免了每个代理类都要重复写的问题,这就是动态代理。

新建一个动态代理类DynamicProxy .java:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxy implements InvocationHandler{
//继承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;
    }

}

然后修改客户类如下:

import java.lang.reflect.Proxy;
public class Test {
    public static void main(String[] args) {
        //构造一个具体要诉讼的人:老罗
        ILawProtocol laoluo=new LaoLuo();
        /**使用动态代理**/
        DynamicProxy dynamicProxy=new DynamicProxy(laoluo);//构造一个动态代理
        //获取被代理类老罗的ClassLoader
        ClassLoader loader=laoluo.getClass().getClassLoader();
        //动态的构造一个代理者律师类
        ILawProtocol lawyerT=(ILawProtocol)Proxy.newProxyInstance(
                loader, 
                new Class[]{ILawProtocol.class}, 
                dynamicProxy);
        //实现ILawProtocol的四个方法:
        lawyerT.submit();
        lawyerT.burden();
        lawyerT.defend();
        lawyerT.finish();
    }
}

打印结果同上。

代理模式除了分为静态代理和动态代理两种分法以外,还有其他按使用场景分类:

  • 远程代理(Remote Proxy): 为一个位于不同地址空间的的对象提供一个本地的代理。
  • 虚拟代理(Virtual Proxy):如果需要创建一个消耗较大的对象,先创建一个消耗较小的对象来表示,真实对象只在需要时才被真实创建。
  • 安全代理(Protection Proxy):用来控制对真实对象的访问权限

Android源码中的代理模式分析

Android源码中有不少的代理模式实现,比如源码里的ActivityManagerProxy代理类,其具体代理的是ActivityManagerNative的子类ActivityManagerService,ActivityManagerService 的功能是负责四大组件的启动/切换/调度、进程的管理/调度等; ActivityManagerService 继承自 ActivityManagerNative 类,并实现了 Watchdog.Monitor 和 BatteryStatsImpl.BatteryCallback 接口;而 ActivityManagerNative 继承自 Binder 类,并实现了 IActivityManager 接口。

class ActivityManagerProxy implements IActivityManager{
        //代码省略...
}

ActivityManagerProxy 实现了IActivityManager接口,该接口定义了Activity相关的接口方法,其中有一些我们在应用开发中也时常接触到。

public interface IActivityManager extends IInterface{
    public int startActivity(){};
    public Intent registerReceiver(){};
    public void unregisterReceiver(){};
    public ComponentName startService(){};
    public int stopService(){};
    public int bindService(){};
    //省略...
}

上面的IActivityManager这个接口类就相当于代理模式中的抽象主题,那么真正的实现主题是什么呢?就是上面我们提到的继承于ActivityManagerNative 的ActivityManagerService类,这几个类之间的关系如下:

这里写图片描述

通过类图,我们可以清晰的看到ActivityManagerProxy和ActivityManagerNative 都实现了IActivityManager接口,严格的说ActivityManagerProxy就是代理部分,ActivityManagerNative 就是真实部分,但ActivityManagerNative 是一个抽象类,并不过多的处理具体逻辑,大部分具体逻辑由其子类ActivityManagerService承担。

ActivityManagerService是系统级的Service并且运行于独立的进程空间中,可以通过ServiceManager来获取它。而ActivityManagerProxy也是运行在独立的进程空间中,两者并不相同,因此ActivityManagerProxy与ActivityManagerService的通信必定是通过跨进程来进行的,从类图中也可以看到,这里跨进程的实现是基于Android的Binder机制,并且此处的代理模式实质是远程代理模式。

ActivityManagerProxy在实际的逻辑处理中并未过多的被外部类引用,因为在Android中管理和维护Activity相关信息的类是另外一个叫做ActivityManager的类,ActivityManager虽然说是管理者Activity的相关信息,但是实质上其大多数逻辑都是由ActivityManagerProxy承担。

下面的类关系图很好的描述了ActivityManagerProxy与ActivityManager之间的调用关系:

这里写图片描述

ActivityManagerService里的源码非常的复杂庞大,后续会继续学习并分享给大家。

总结

通过本篇文章需要掌握以下几点:
(1)代理模式的定义及使用场景,并会简单使用;
(2)理解动态代理和静态代理的区别;
(3)理解InvocationHandler和Proxy.newProxyInstance的使用;

推荐文章:
1 http://yangguangfu.iteye.com/blog/815787
将代理模式的三种角色与水浒传里相关人物对应起来,很形象生动,Big赞。

DEMO下载

1
0
查看评论

Android下静态代理和动态代理解析

1.相关概念1.1 代理 在某些情况下,我们不希望或是不能直接访问对象 A,而是通过访问一个中介对象 B,由 B 去访问 A 达成目的,这种方式我们就称为代理。 这里对象 A 所属类我们称为委托类,也称为被代理类,对象 B 所属类称为代理类。 代理优点有:隐藏委托类的实现 解耦,不改变委托类代码...
  • IsMrWu
  • IsMrWu
  • 2016-11-06 21:21
  • 1005

Android设计模式之代理模式 Proxy

一.概述 代理模式也是平时比较常用的设计模式之一,代理模式其实就是提供了一个新的对象,实现了对真实对象的操作,或成为真实对象的替身.在日常生活中也是很常见的.例如A要租房,为了省麻烦A会去找中介,中介会替代A去筛选房子,A坐享中介筛选的结果,并且交房租也是交给中介,这就是一个典型的日...
  • l2show
  • l2show
  • 2015-07-28 22:14
  • 20609

Proxy代理模式经典实例(绝对OOP)

  • 2008-04-03 20:41
  • 1KB
  • 下载

Android开发中无处不在的设计模式——动态代理模式

继续更新设计模式系列,写这个模式的主要原因是最近看到了动态代理的代码。 先来回顾一下前5个模式: - Android开发中无处不在的设计模式——单例模式 - Android开发中无处不在的设计模式——Builder模式 - Android开发中无处不在的设计模式——观察者模式 - ...
  • sbsujjbcy
  • sbsujjbcy
  • 2016-01-21 11:37
  • 7576

代理模式在android中使用

代理设计模式是对象的结构模式,原理就是给某个对象提供一个代理对象,并由代理对象来控制对愿对象的引用。在有些情况下,一方不能或不想直接引用一个对象,而代理对象可以在双方之间起到中介的作用,这样可以大大降低彼此的耦合关系,提高彼此的灵活性。
  • why_2012_gogo
  • why_2012_gogo
  • 2015-04-29 16:02
  • 1133

Android设计模式之动态代理,实现方法拦截功能

动态代理的好处: 1.代理方式多样,自由定义,比如可以查看被代理类的各方法执行时间。 2.当被代理对象改变其内部实现时,不影响代理规则。动态代理的局限性: 1.只能代理interface方法以拦截Button的onClick方法为例说明下我们的动态代理模式: 1.首先创建一个OnClickL...
  • qq_21146289
  • qq_21146289
  • 2016-12-11 20:21
  • 221

Android设计模式源码解析之Proxy模式

Android设计模式源码解析之Proxy模式 本文为 Android 设计模式源码解析 中 Proxy模式 分析 Android系统版本: 5.0 分析者:singwhatiwanna,分析状态:完成,校对者:Mr.Simple,校对状态:已校对 Binder中的代理模...
  • singwhatiwanna
  • singwhatiwanna
  • 2015-03-24 12:58
  • 14957

Android设计模式之代理模式(Proxy Pattern)

代理模式介绍代理模式(Proxy Pattern)也称为委托模式,是结构型设计模式的一种,代理模式在各类开发中运用的相当广泛,不论是j2ee,android还是ios,都能看到它的身影,所以说设计模式无处不在。代理模式的定义:为其他对象提供一种代理以控制这个对象的访问。通俗一点:找别人做你想做但是做...
  • happy_horse
  • happy_horse
  • 2016-05-31 13:31
  • 1562

设计模式总结之Proxy Pattern(代理模式)

为其他对象提供一种代理以控制对这个对象的访问。
  • cooldragon
  • cooldragon
  • 2016-08-11 00:50
  • 1244

设计模式(结构型)之代理模式(Proxy Pattern)

代理模式是常用的结构型设计模式之一,当无法直接访问某个对象或访问某个对象存在困难时可以通过一个代理对象来间接访问,为了保证客户端使用的透明性,所访问的真实对象与代理对象需要实现相同的接口。根据代理模式的使用目的不同,代理模式又可以分为多种类型,例如保护代理、远程代理、虚拟代理、缓冲代理等,它们应用于...
  • yanbober
  • yanbober
  • 2015-05-04 18:48
  • 5694
    个人资料
    • 访问:183882次
    • 积分:2775
    • 等级:
    • 排名:第15269名
    • 原创:102篇
    • 转载:9篇
    • 译文:1篇
    • 评论:24条
    博客专栏
    最新评论