1、简介

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

分类

  1. 静态代理(静态定义代理类,我们自己静态定义的代理类)
  2. 动态代理(通过程序动态生成代理类,该代理类不是我们自己定义的。而是由程序自动生成)-- 这是与静态代理主要的区别!!!

主要解决:在直接访问对象时带来的问题,直接访问会给使用者或者系统结构带来很多麻烦,我们可以在访问此对象时加上一个对此对象的访问层;

何时使用:想在访问一个类时做一些控制;

如何解决:增加中间层;

应用实例:JDK自带的动态代理,CGLIB,Spring AOP,....

英文:Proxy

类型:结构型模式

2、类图及组成

)类图

代理模式一般会有三个角色:

  抽象角色:指代理角色(经纪人)和真实角色(明星)对外提供的公共方法,一般为一个接口

  真实角色:需要实现抽象角色接口,定义了真实角色所要实现的业务逻辑,以便供代理角色调用。也就是真正的业务逻辑在此。

  代理角色:需要实现抽象角色接口,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。

  将统一的流程控制都放到代理角色中处理!

3、静态代理

3-1、实例引入:电影明星通过经纪人实现日常活动

定义一个抽象角色:

package com.designpattern.proxy.staticproxy;
/*** 定义一个抽象角色:电影明星* @author Json
*/
public interface MovieStar {/*** 找电影合作*/void discussCooperation();/*** 签合同*/void signContract();/*** 出演电影角色*/void playRoleInMovie();/*** 收演出费*/void collectMoney();
}

定义一个具体角色:

package com.designpattern.proxy.staticproxy;
/*** 真实角色:电影明星* @author Json
*/
public class RealMovieStar implements MovieStar {@Overridepublic void discussCooperation() {System.out.println("真实角色:discussCooperation()");}@Overridepublic void signContract() {System.out.println("真实角色:signContract()");}@Overridepublic void playRoleInMovie() {System.out.println("真实角色:playRoleInMovie()");}@Overridepublic void collectMoney() {System.out.println("真实角色:collectMoney()");}
}

定义一个代理类:经纪人

package com.designpattern.proxy.staticproxy;
/*** 代理角色:经纪人* @author Json
*/
public class ProxyMovieStar implements MovieStar {/*** 真实对象的引用*/private MovieStar star;public ProxyMovieStar(MovieStar star){this.star = star;}@Overridepublic void discussCooperation() {System.out.println("代理角色:discussCooperation()");}@Overridepublic void signContract() {System.out.println("代理角色:signContract()");}@Overridepublic void playRoleInMovie() {star.playRoleInMovie();   //这个需要真实角色实现的操作}@Overridepublic void collectMoney() {System.out.println("代理角色:collectMoney()");}
}

下面测试一下:

package com.designpattern.proxy.staticproxy;
/*** 测试* @author Json
*/
public class Test {public static void main(String[] args) {RealMovieStar real = new RealMovieStar();MovieStar proxy = new ProxyMovieStar(real);proxy.discussCooperation();proxy.signContract();proxy.playRoleInMovie();//需要真实对象实现操作(出演电影)proxy.collectMoney();}
}

结果:

代理角色:discussCooperation()
代理角色:signContract()
真实角色:playRoleInMovie()
代理角色:collectMoney()

3-2、优缺点

优点:

  业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。

缺点:

  1、代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
  2、代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理要是应用在程序规模稍大时就比较糟糕了。

4、动态代理

4-1、实例引入

抽象角色、真实角色与静态代理一致:

package com.designpattern.proxy.dynamicproxy;
/*** 定义一个抽象角色:电影明星* @author Json
*/
public interface MovieStar {/*** 找电影合作*/void discussCooperation();/*** 签合同*/void signContract();/*** 出演电影角色*/void playRoleInMovie();/*** 收演出费*/void collectMoney();
}

package com.designpattern.proxy.dynamicproxy;
/*** 真实角色:电影明星* @author Json
*/
public class RealMovieStar implements MovieStar {@Overridepublic void discussCooperation() {System.out.println("真实角色:discussCooperation()");}@Overridepublic void signContract() {System.out.println("真实角色:signContract()");}@Overridepublic void playRoleInMovie() {System.out.println("真实角色:playRoleInMovie()");}@Overridepublic void collectMoney() {System.out.println("真实角色:collectMoney()");}
}

代理角色变成了代理角色处理器:

package com.designpattern.proxy.dynamicproxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;/*** 代理角色的处理器* @author Json
*/
public class ProxyMovieStarHandler implements InvocationHandler {private MovieStar moviestar;public ProxyMovieStarHandler(MovieStar moviestar){super();this.moviestar = moviestar;}/*** 所有的流程控制都在invoke方法中* proxy:代理类* method:正在调用的方法* args:方法的参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object object = null;System.out.println("调用之前的处理逻辑");if (method.getName().equals("playRoleInMovie")) {object = method.invoke(moviestar, args);//激活调用的方法   }System.out.println("调用之后的处理逻辑");return object;}
}

测试:

package com.designpattern.proxy.dynamicproxy;import java.lang.reflect.Proxy;
/*** 测试* @author Json
*/
public class Test {public static void main(String[] args) {MovieStar star = new RealMovieStar();//处理器ProxyMovieStarHandler handler = new ProxyMovieStarHandler(star);//代理类MovieStar proxyMovieStar = (MovieStar) Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{MovieStar.class}, handler);//调用代理类的playRoleInMovie,实际调用的是真实角色的playRoleInMovieproxyMovieStar.playRoleInMovie();}
}

结果:

调用之前的处理逻辑
真实角色:playRoleInMovie()
调用之后的处理逻辑

4-2、优缺点

优点:

  动态代理与静态代理相比较,最大的好处是接口中声明的所有方法都被转移到调用处理器一个集中的方法中处理(InvocationHandler.invoke);而不用一个一个的写代理类,这样,在接口方法数量比较多的时候,我们可以进行灵活处理,而不需要像静态代理那样每一个方法进行中转。而且动态代理的应用使我们的类职责更加单一,复用性更强;

缺点:

  那就是只能代理基于接口的类,而无法代理没有接口的委托类。关于这一点,可以使用CGLib类库来做到代理无接口类。

5、使用场景

  按职责来划分,通常有以下使用场景:

    1、远程代理 
    2、虚拟代理 
    3、Copy-on-Write 代理
    4、保护(Protect or Access)代理
    5、Cache代理
    6、防火墙(Firewall)代理
    7、同步化(Synchronization)代理 
    8、智能引用(Smart Reference)代理

6、与其他模式的对比

  1、和适配器模式的区别:  适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。
              适配器为它所适配的对象提供了一个不同的接口,代理提供了与它的实体相同的接口。
              PS: 用于访问保护的代理可能会拒绝执行实体会执行的操作,因此,它的接口实际上可能只是实体接口的一个子集。

  2、和装饰器模式的区别: 装饰器模式为了增强功能,而代理模式是为了加以控制。

7、总结

静态代理与动态代理,它们都能实现相同的功能,而我们看从静态代理到动态代理的这个过程,我们会发现其实动态代理只是对类做了进一步抽象和封装,使其复用性和易用性得到进一步提升;

PS:源码地址   https://github.com/JsonShare/DesignPattern/tree/master

PS:原文地址 http://www.cnblogs.com/JsonShare/p/7161324.html

转载于:https://www.cnblogs.com/JsonShare/p/7161324.html

设计模式解密(7)- 代理模式相关推荐

  1. 设计模式学习之代理模式学习(一)

    设计模式学习之代理模式学习(一) 关于设计模式想必学习过Java语言的人都知道吧,当时对其进行深入学习的的人应该不是很多.在我看来设计方面的知识相比于框架应用配置等知识要有意思的多,并且设计模式的对一 ...

  2. 设计模式之静态代理模式实战

    转载自 设计模式之静态代理模式实战 静态代理模式很简单,代理类和实现类都实现相同的接口,然后通过代理类来调用实现类的方法. 如我们想保存用户信息之前打印用户信息,或者保存用户信息之后把这些信息缓存下来 ...

  3. 设计模式之蝉——代理模式上中

    代理模式的扩展 1 普通代理 :这种代理就是客户端只能访问代理角色,而不能访问真实角色.与设计模式之蝉--代理模式上 片基本差不多. (1)Subject抽象主题角色: (2)RealSubject具 ...

  4. 每日一个设计模式之【代理模式】

    文章目录 每日一个设计模式之[代理模式] ☁️前言

  5. 大话设计模式C++版——代理模式

        本篇開始前先发个福利,程杰的<大话设计模式>一书高清电子版(带文件夹)已上传至CSDN,免积分下载. 下载地址:http://download.csdn.net/detail/gu ...

  6. Java24种设计模式(第二种)--代理模式(Proxy Pattern)

    Java24种设计模式 (第二种) 一.代理模式(Proxy Pattern) 模式逻辑: 什么是代理模式呢?我很忙,忙的没空理你,那你要找我呢就先找我的代理人吧,那代理人总要知道 被代理人能做哪些事 ...

  7. 23种java设计模式详解-代理模式

    什么是代理模式: Proxy模式又叫做代理模式,是构造型的设计模式之一,它可以为其他对象提供一种代理(Proxy)以控制对这个对象的访问.所谓代理,是指具有与代理元(被代理的对象)具有相同的接口的类, ...

  8. 设计模式:4.代理模式

    代理模式 代理模式属于结构型模式 定义:为其他对象提供一种代理以控制对这个对象的访问 代理模式就是在操作原对象的时候,多出来一个代理类,用来对原对象的访问进行控制和替代原对象进行一些操作 模式类图 角 ...

  9. 《设计模式系列》- 代理模式

    有情怀,有干货,微信搜索[三太子敖丙]关注这个有一点点东西的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文 ...

  10. 【C++设计模式】-03代理模式

    代理模式 代理模式介绍 今天继续学习设计模式,今天我们来学习代理模式.其实这个模式呢在我们的生活早已经运用起来了.笔者看到这个模式就联想到了代理商.我们客户买东西一般都是经过代理商的,代理商和真正的生 ...

最新文章

  1. C语言 | C语言中的输出函数:printf()
  2. vs2019新建android生成app,VS2017 VS2019创建离线安装包
  3. HTML作业-潮流服装网页
  4. html保存按钮代码_如何防止Joomla编辑器删除HTML代码
  5. 把Arraylist转换成GameObject[]
  6. Linux的Netfilter框架深度思考-对比Cisco的ACL
  7. 清除浮动的方法以及优缺点
  8. 京瓷1020手动双面打印提示_解决京瓷2201复印机不能双面打印问题
  9. UCGUI使用的24位颜色RGB数值对照表
  10. Eclipse将控制台输出信息保存为文件
  11. JAVA.犹抱琵琶半遮面
  12. 解密weblogic控制台账号密码
  13. linux hd4000显卡驱动,AMD Radeon HD 2000/HD 3000/HD 4000系列显卡驱动怎么样
  14. m4a怎么转换成mp3,4招搞定
  15. #日常---恒权码与变权码
  16. CVPR 2023 | 白翔团队提出:将CLIP模型用于场景文本检测
  17. 线程池有哪些状态?状态是如何转换的?
  18. iPhone越狱的利与弊
  19. 桌面级创客工具 创客造物空间
  20. 利用R语言预测银行客户信用的优劣(随机森林方法)

热门文章

  1. 黑马博客——详细步骤(八)项目功能的实现之另一种分页方式【mongoose-sex-page】
  2. HEVC: 整个编码流程以及相关的函数介绍
  3. 企业级实际性能测试案例与经验分享
  4. 毕业从事汽车行业,转行测试工程师,3个月完成了蜕变,我很满意...
  5. 如何搭建测试平台?理清思路很重要
  6. 你该怎么去学软件测试,过来人告诉你
  7. mysql c接口_mysql C语言API接口及实例
  8. Qt与MySQL的连接与基本操作
  9. mysql 日期 1970_Mysql中处理1970年前的日期(unixtime为负数的情况)负数时间戳格式化...
  10. php配合jade使用,详解基于模板引擎Jade的应用