24. 代理模式

定义

代理模式(Proxy Pattern):给某一个对象提供一个代理或占位符,并由代理对象来控制对原对象的访问。

通俗理解

在好几年前,买火车票和飞机票总要在线下买。可以在火车站、机场买,当然并不是每一个人都在火车站、机场旁边,如果走很远的路就为了一张票,就太浪费时间了,所以随地可见的火车、飞机票代售点就成为大家买票的最佳选择。

火车、飞机票代售点是火车站、机场的一个代理商,它可以完成火车票、飞机票的销售,同时,还可以在这上面添加自己的功能,例如可以卖一些保险、旅途中的附加服务等等。当然,这其中也有代售点不可以做的工作,其中重要的一点就是代售点不可以进行退票的工作,要退票,只能去火车站、机场。

代理模式就是这样一个场景。如果一个接口很难进行访问,那么我们可以在这个接口上面封装一层代理类,用代理类去调取这个接口,然后我们的系统调取代理类。并且在代理类上面可以封装自己的方法,使得接口更符合我们系统,更加易用。

示例

以火车代售点作为实例。

渣渣程序

车站接口以及实现

public interface IStation {
    void saleTicket();
}
public class StationImpl implements IStation {
    public void saleTicket() {
        System.out.println("火车站卖出一张车票");
    }
}

程序主入口

public class Main {
    public static void main(String[] args) {
        IStation station = new StationImpl();
        station.saleTicket();//火车站卖出一张车票
    }
}

上面就是完全没有使用代理模式的代码,直接调用车站的代码,就相当于直接去车站买车票一样。当然不是不可以,但是像前面讲的一样,有时候我们去不了车站或者不想去车站的情况下,那么这种写法就不适合了。

优化

普通代理

车站接口以及实现不变,添加StationProxy的类,实现对Station的代理,程序如下:

public class StationProxy implements IStation {
    private IStation station;
    public void saleTicket() {
        if(station == null) {
            station = new StationImpl();
        }
        System.out.println("连接火车站系统连接");
        station.saleTicket();
        System.out.println("断开火车站系统连接");
    }
}

程序入口

public class Main {
    public static void main(String[] args) {
        IStation station = new StationProxy();
        station.saleTicket();
        //连接火车站系统连接
        //火车站卖出一张车票
        //断开火车站系统连接
    }
}

这样就实现了对火车站的代理,并且在代理的方法上面添加了自己系统的方法。要注意的是,这里使用了懒加载的方式,只有在调用代理方法的时候才会初始化对象,这个过程叫懒加载,有利于改善系统性能。

动态代理

Java提供了反射的方式,可以动态加载类,这样绕过了编译,也让系统实现更加灵活。同时,在代理模式当中,也可以使用动态代理的方式。

车站接口以及实现不变,创建动态代理的处理类。

动态代理处理类

public class StationHandler implements InvocationHandler {
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object obj = new StationImpl();
        System.out.println("代理类:" + proxy.getClass().getName()
                + "调用:"+obj.getClass().getName()
                + "代理方法:"+method.getName());
        Object invoke = method.invoke(obj, args);
        System.out.println("调用结束");
        return invoke;
    }
}

程序主入口

public class Main {
    public static void main(String[] args) {
        IStation stationProxy = (IStation) Proxy.newProxyInstance(
                Thread.currentThread().getContextClassLoader(),
                new Class[]{IStation.class},
                new StationHandler()
                );
        stationProxy.saleTicket();
        //代理类:com.sun.proxy.$Proxy0调用:com.wusicheng.e24_proxy_pattern.nevv.dynamic.StationImpl代理方法:saleTicket
        //火车站卖出一张车票
        //调用结束
    }
}

动态代理是框架的基础,AOP就是这么实现的。如果跟踪源代码,可以看到大量的invoke,$proxy(),他们用的就是动态代理。这里不做深入,以后读源代码的时候再深入,现在知道,会写就可以了。

优点

  1. 协调调用者和被调用者,降低系统的耦合度;
  2. 客户端可以对调用发进行编程,增加或者修改代理类的时候,不需要修改源代码就可以实现,符合“开闭原则”。

缺点

  1. 封装了一层,系统可能会变慢;
  2. 实现代理需要额外的工作,有些的实现过程比较复杂。

应用场景

  1. 对象载入时间长的,需要知道中间状态的;
  2. 在远程计算机上,访问困难时间长,需要鉴权的;
  3. 频繁查询和引用的;
  4. 多线程中使用保证安全的;
  5. 某对象被多个对象引用,其中的引用需要被改写的时候复制出来的;
  6. 对象的使用时需要自动做其他工作的。

吐槽

就是在原来的对象上面封装一层。

程序

e24_proxy_pattern

https://www.jianshu.com/p/ab6d5853b24e

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

推荐阅读更多精彩内容

  • 参考资料:菜鸟教程之设计模式 设计模式概述 设计模式(Design pattern)代表了最佳的实践,通常被有经验...
    Steven1997阅读 1,162评论 1 12
  • 创建型模式 工厂模式 工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设...
    隔墙送来秋千影阅读 2,644评论 0 11
  • 真诚的,TNANKS。 个人Github-23种设计模式案例链接 创建型模式 工厂模式 工厂模式(Factory ...
    水清_木秀阅读 26,001评论 11 204
  • 昨天和两个死党一起去看的电影,那么就顺路说说他俩吧。 下午的两个死党,一个叫刘备,一个叫肥叔。 先说刘备吧,...
    LV741阅读 314评论 0 0
  • 宝贝儿,今天是你上小托班的第三天,早晨醒来,你就一边往被窝儿里钻,一边说想在家睡觉,不想去上学,黏黏的声音里透着任...
    曹晓红简书阅读 472评论 9 9