【设计模式笔记】(十六)- 代理模式

一、简述

代理模式(Proxy Pattern),为其他对象提供一个代理,并由代理对象控制原有对象的引用;也称为委托模式。

其实代理模式无论是在日常开发还是设计模式中,基本随处可见,中介者模式中的中介者对象也是代理模式的应用,其他的对象的交互都是交给了中介者对象处理的。而在生活中就更多类似代理模式的例子,例如:抢票插件、科学上网等等。

代理模式
  • Subject:抽象主题类(也可以是接口),声明共同方法
  • RealSubject:真实主题类,也就是被代理类,负责执行具体的业务逻辑方法;客户类调用代理类简介调用其定义的方法
  • ProxySubject:代理主题类,也就是代理类,持有一个被代理类的真是对象,在实现抽象主题类的共同方法中调用被代理类相应的方法,起到代理的作用
  • Client:客户类,使用代理对象的类
/**抽象主题*/
public interface Subject {
    public void visit();
}

/**被代理主题*/
public class RealSubject implements Subject {
    @Override
    public void visit() {
        System.out.print("this is real subject");
    }
}

/**代理主题*/
public class ProxySubject implements Subject {
    //真实主题
    private Subject realSubject;

    public ProxySubject(@NotNull Subject subject){
        realSubject = subject;
    }

    @Override
    public void visit() {
        System.out.print("proxy start");
        realSubject.visit();
        System.out.print("proxy end");
    }
}

/**客户类*/
public class Client {
    public static void main(String[] args){
        //创建被代理对象
        RealSubject realSubject = new RealSubject();
        //创建代理对象
        ProxySubject proxySubject = new ProxySubject(realSubject);
        //调用方法
        proxySubject.visit();
    }
}

输出结果:
proxy start
this is real subject
proxy end

二、动态代理

上一部分中所讲述的,其实是静态代理,也就是在代码的编译阶段生成代理类来完成代理对象的一系列操作。而动态代理则是在运行时动态生成代理类对象。代理对象的生成是利用JDKjava.lang.reflect.Proxy类,使用newProxyInstance方法可以创建一个我们所需要的代理对象

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) throws IllegalArgumentException {
//代码省略...
}

newProxyInstance方法是Proxy的一个静态方法,并且接收三个参数

  • ClassLoader loader:类加载器
  • Class<?>[] interfaces:目标对象实现的接口的类型
  • InvocationHandler h:处理事件的对象,InvocationHandler是一个接口,执行目标对象的方法,会触发InvocationHandlerinvoke方法

其中InvocationHandlerinvoke方法如下:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;`

  • Object proxy:执行方法的代理对象
  • Method method:被执行的方法的对象
  • Object[] args:被执行的方法的参数
    返回值则是代理对象调用方法时所返回的值

依然使用Subject作为例子,看看简单的代码实现(代码没有封装)

//创建被代理对象
Subject realSubject = new RealSubject();
//创建代理对象
Subject subject = (Subject) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(),
    new Class[]{Subject.class},
    new InvocationHandler() {
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return method.invoke(realSubject, args);
        }
    });
subject.visit();

从代码上来看,比之前的静态代理要简单很多,没有那么多的类和对象;但是相对的在代码性能上有所牺牲,而且对于不太熟悉反射相关的知识的开发者并不是太友好。

通过反射类ProxyInvocationHandler回调接口实现的JDK动态代理,要求被代理类必须实现一个接口,但事实上并不是所有类都有接口,对于没有实现接口的类,便无法使用该方方式实现动态代理。

三、其他代理分类

静态代理和动态代理是代码方面来区分的代理模式,也可以从适用范围来区分不同类型的代理实现

  • 远程代理(Remote Proxy):为某个对象在不同的内存地址空间提供局部代理。使系统可以将Server部分的实现隐藏,以便Client不必考虑Server的存在
  • 虚拟代理(Virtual Proxy):使用一个代理对象表示一个十分耗资源的对象并在真正需要时才创建
  • 保护代理(Protection Proxy):使用代理控制对原始对象的访问。该类型的代理常被用于原始对象有不同访问权限的情况。
  • 智能引用(Smart Reference):在访问原始对象时执行一些自己的附加操作并对指向院士对象的引用计数

这里要注意的是,静态和动态代理都可以应用于上述4种情形,两者是各自独立的变化。

四、总结

代理模式使用非常广泛,基本在其他的设计模式中也能看到代理模式的影子,但是使用时针对性较强,而且模式本身并没有什么突出的优缺点,基本上可以放心使用

PS:从此你写过的代码都像代理模式

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

推荐阅读更多精彩内容