Android设计模式-代理模式

UML关系简单介绍
UML简单使用的介绍
创建型设计模式
Android设计模式-单例模式
Android设计模式-工厂模式
Android设计模式-抽象工厂模式
Android设计模式-建造者模式
Android设计模式-原型模式
结构型设计模式
Android设计模式-代理模式
Android设计模式-装饰模式
Android设计模式-适配器模式
Android设计模式-组合模式
Android设计模式-门面模式
Android设计模式-桥接模式
Android设计模式-享元模式
行为型设计模式
Android设计模式-策略模式
Android设计模式-命令模式
Android设计模式-责任链模式
Android设计模式-模版方法模式
Android设计模式-迭代器模式
Android设计模式-观察者模式
Android设计模式-备忘录模式
Android设计模式-中介者模式
Android设计模式-访问者模式
Android设计模式-状态模式
Android设计模式-解释器模式

1.定义

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

2.代理模式通用类图

代理模式通用类图

角色介绍

  • Subject 抽象主题,可以是抽象类也可以是接口,realsubject和proxy都是继承或者实现自它。
  • RealSubject 真实主题类,也就是被代理者,也就是具体任务逻辑的执行者
  • Proxy 代理类,也叫委托类,一般持有真实主题类的引用,在相应的方法中,调用真实主题类的对应方法。

3.简单实现

3.1抽象主题类

public interface Subject {
    void doSomething();
}

3.2 真实主题类

public class RealSubject implements Subject {
    @Override
    public void doSomething() {
        System.out.println("买肉!");
    }
}

3.3 代理类

public class ProxySubject implements Subject {
    Subject subject=null;

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void doSomething() {
        doBefore();
        System.out.println("我代理者,我要!!");
        this.subject.doSomething();
        doAfter();
    }

    private void doBefore(){
        System.out.println("我是代理者前置动作");

    }

    private void doAfter(){
        System.out.println("我是代理者后置动作");

    }
}

3.4场景调用

public class MyClass {
    public static void main(String args[]) {
        Subject realSubject=new RealSubject();
        Subject proxySubject=new ProxySubject(realSubject);
        proxySubject.doSomething();
    }
}

打印结果为

我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作

3.5例子简介

被代理类realSubject与代理类proxySubject都实现了接口Subject,比如你想去买肉吃了,realSubject就是你,但是你不想动弹,就让你都舍友帮你去买肉回来,proxySubject就相当于你的舍友。你舍友肯定是要知道他是帮谁买肉的,否则回来谁给钱呀。。这个目标就是通过构造函数传过来的subject,也就是在场景类中传过来的realSubject。另外代理模式,也常可在代理的方法执行前后,插入一些自己的逻辑,比如上例中的doBefore和doAfter。

4.扩展

4.1普通代理和强制代理

普通代理就是我们要知道代理的存在,也就是代理类后才能访问。而强制代理则是调用者直接调用真实角色而不用关心代理是否存在,其代理的产生是由真实角色决定的

4.1.1普通代理

修改上面的例子,将其改为普通代理模式

4.1.1.1 抽象主题类

public interface Subject {
    void doSomething();
}

4.1.1.2 真实主题类

public class RealSubject implements Subject {

    public RealSubject(Subject subject) throws Exception{
        if (subject==null){
            throw new Exception();
        }
    }

    @Override
    public void doSomething() {
        System.out.println("买肉!");
    }
}

4.1.1.3 代理类

public class ProxySubject implements Subject {
    private Subject subject=null;

    public ProxySubject() {
        try {
            subject=new RealSubject(this);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    @Override
    public void doSomething() {
        doBefore();
        System.out.println("我代理者,我要!!");
        this.subject.doSomething();
        doAfter();
    }

    private void doBefore(){
        System.out.println("我是代理者前置动作");

    }

    private void doAfter(){
        System.out.println("我是代理者后置动作");

    }
}

4.1.1.4 场景调用

public class MyClass {
    public static void main(String args[]) {

        Subject proxySubject=new ProxySubject();
        proxySubject.doSomething();
    }
}

打印结果为

我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作

4.1.1.5 例子总结

从打印结果中,可以看出,在该模式下,没有发生变化,但是在调用的时候,只需要调用代理类就可以进行相应的任务,不用知道具体的真实主题类是谁。屏蔽了真实角色的变更对高层模块的影响,真实主题类想怎么修改就怎么修改,对高层次模块没有任何影响,只要你实现了对应的方法,对扩展性较高对场合特别适合。

4.1.2 强制代理

强制代理简单理解为就是必须通过真实主题类获得的代理,才能进行相应的操作。就相当于高层模块new了一个真实主题类,但是返回的确实一个代理角色。
将上面的例子修改为强制代理

4.1.2.1 抽象主题类

public interface Subject {
    void doSomething();
}

4.1.2.2 真实主题类

public class RealSubject implements Subject {
    private Subject proxySubject=null;

    public RealSubject() {

    }

    public Subject getProxySubject(){
        this.proxySubject=new ProxySubject(this);
        return this.proxySubject;
    }

    @Override
    public void doSomething() {
        if (proxySubject!=null) {
            System.out.println("买肉!");
        }else {
            System.out.println("请使用指定的代理进行访问");
        }

    }
}

4.1.2.3 代理类

public class ProxySubject implements Subject {
    private Subject subject=null;

    public ProxySubject(Subject subject) {
        this.subject = subject;
    }

    @Override
    public void doSomething() {
        doBefore();
        System.out.println("我代理者,我要!!");
        this.subject.doSomething();
        doAfter();
    }

    private void doBefore(){
        System.out.println("我是代理者前置动作");

    }

    private void doAfter(){
        System.out.println("我是代理者后置动作");

    }
}

4.1.2.4 场景调用

public class MyClass {
    public static void main(String args[]) {

        Subject real=new RealSubject();
        real.doSomething();
    }
}

打印结果为
请使用指定的代理进行访问

public class MyClass {
    public static void main(String args[]) {

        Subject real=new RealSubject();
        Subject proxy=new ProxySubject(real);
        proxy.doSomething();
    }
}
打印结果为
我是代理者前置动作
我代理者,我要!!
请使用指定的代理进行访问
我是代理者后置动作

public class MyClass {
    public static void main(String args[]) {

        Subject real=new RealSubject();
        Subject proxy=((RealSubject) real).getProxySubject();
        proxy.doSomething();
    }
}
打印结果为
我是代理者前置动作
我代理者,我要!!
买肉!
我是代理者后置动作

4.1.2.5例子总结

以上的例子即为强制代理,调用的时候,只能通过真实角色指定的代理角色,才能访问具体的功能逻辑,不允许直接访问真实角色。高层模块只要调用getProxySubject就可以获取访问真实角色的指定代理类,不需要重新产生一个新的代理类。

4.2动态代理

动态代理在实现阶段不管关心代理谁,而在运行阶段才指定代理那一个对象。现在很流行的一个aop编程,核心就是使用了动态代理技术。
动态代理主要用到了InvocationHandler类

4.2.1动态代理简单实现

动态代理类

public class DynamicProxy implements InvocationHandler {
    //被代理的对象
    private Object object;

    public DynamicProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("我是动态代理!");
        Object result=method.invoke(object,objects);
        return result;
    }
}

真实主题类

修改回最初的样子。。。

public class RealSubject implements Subject {
    private Subject proxySubject=null;

    public RealSubject() {

    }

//    public Subject getProxySubject(){
//        this.proxySubject=new ProxySubject(this);
//        return this.proxySubject;
//    }

    @Override
    public void doSomething() {
//        if (proxySubject!=null) {
            System.out.println("买肉!");
//        }else {
//            System.out.println("请使用指定的代理进行访问");
//        }

    }
}

场景类调用

public class MyClass {
    public static void main(String args[]) {

        Subject real=new RealSubject();
        DynamicProxy dynamic=new DynamicProxy(real);
        ClassLoader classLoader=real.getClass().getClassLoader();
        Subject dynamicSubject= (Subject) Proxy.newProxyInstance(classLoader,new Class[]{Subject.class},dynamic);
        dynamicSubject.doSomething();
    }
}

打印结果为
,
我是动态代理!
买肉!

动态代理总结

动态代理是在程序运行期间根据反射等机制动态的生成。代理类和委托类的关系是在程序运行期确定的。
另外动态代理如果想要在相应位置添加前后操作,则可以在动态代理类中添加

 @Override
    public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
        System.out.println("我是动态代理!");
        if (method.getName().equalsIgnoreCase("doSomething")){
            System.out.println("插入点什么??");
        }
        Object result=method.invoke(object,objects);
        return result;
    }

打印结果为
我是动态代理!
插入点什么??
买肉!

本质上,这就是aop,具体aop的东西自行搜索吧,这里扯远了。。

总结

代理模式是常用的结构型设计模式之一,它为对象的间接访问提供了一个解决方案,可以对对象的访问进行控制

优点

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

推荐阅读更多精彩内容

  • 游戏 书中用游戏来引入代理模式,游戏大家都玩过,基本套路就是打怪升级,我们把这段打游戏的过程系统化,非常简单的一个...
    stayiwithime阅读 906评论 0 0
  • 1.代理模式定义   为其他对象提供一种代理控制这个对象的访问。说白了就是我们生活中的经纪人,我们想要做什么事情,...
    如愿以偿丶阅读 315评论 0 1
  • 整体Retrofit内容如下: 1、Retrofit解析1之前哨站——理解RESTful 2、Retrofit解析...
    隔壁老李头阅读 3,214评论 2 10
  • 我是游戏至尊 2007年,感觉很无聊,于是就玩了一段时间的网络游戏,游戏名就不说了,要不就有做广告的嫌疑,反正就是...
    WILL_HUNTING阅读 422评论 0 0
  • 一.核心思想 为其他对象提供代理以控制对这个对象的访问,代理对象起到了中介作用,不影响其他对象原有的功能,可以在其...
    liys_android阅读 437评论 0 0