正文

一、定义

代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。

要点:

  • 代理模式为一个对象创建了代理对象,让代理对象控制对该对象的访问。被代理的对象可以是远程的对象、创建开销大的对象或者需要安全控制的对象。
  • 代理类型:远程代理、虚拟代理、保护代理等。
    • 远程代理:控制访问远程对象。
    • 虚拟代理:控制访问创建开销大的资源。
    • 保护代理:基于权限控制对资源的访问。

二、实现步骤

1、创建主题接口

/*** 主题接口*/
public interface Subject {/*** 请求主题执行某种动作*/void request();
}

2、创建真实主题(被代理类),并继承主题接口

真实主题是真正做事的主题对象。

/*** 真正做事的真实主题(被代理类)*/
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject do something...");}
}

3、创建主题代理(代理类),并继承主题接口

主题代理持有真正做事的真实主题,并控制对真实主题的访问。

/*** 主题代理(代理类)*/
public class SubjectProxy implements Subject {/*** 持有真实主题*/RealSubject realSubject;@Overridepublic void request() {System.out.println("SubjectProxy receives and controls request, and entrust request to RealSubject...");// 代理并控制对真实主题的访问,比如权限控制、访问资源控制等if (realSubject == null) {realSubject = new RealSubject();}// ...// 将请求委托给真实主题realSubject.request();}
}

4、使用主题代理访问主题

public class Test {public static void main(String[] args) {// 代理SubjectProxy proxy = new SubjectProxy();// 通过代理请求主题proxy.request();}
}

三、举个栗子

1、背景

我们打算建立一个应用程序,用来展示你最喜欢的 CD 封面。CD 封面的图我们可以从一些网站的在线服务中获取。

唯一的问题是,限于连接带宽和网络负载,下载可能需要一些时间,所以在等待图像加载时,应该显示一些东西。我们也不希望在等待图像时,整个应用程序被挂起。一旦图像被加载完成,刚才显示的东西应该消失,然后图像显示出来。

2、实现

使用虚拟代理管理图片的加载、显示。

(1)创建图片接口

/*** 图片接口*/
public interface Image {/*** 绘图*/void paint();
}

(2)创建真正做事的图片类

/*** 真正进行图片操作的真实图片类*/
public class RealImage implements Image {String url;String description;public RealImage(String url,  String description) {this.url = url;this.description = description;load(url);}@Overridepublic void paint() {System.out.println("Image is painted");}/*** 模拟加载图片*/private void load(String url) {try {System.out.println("Loading image from: " + url);for (int i = 0; i < 10; i++) {System.out.print("===");Thread.sleep(200);}System.out.println("===>100%");System.out.println("Loading image is finished!");} catch (InterruptedException e) {e.printStackTrace();}}
}

(3)创建图片代理

/*** 图片代理*/
public class ImageProxy implements Image {RealImage realImage;String imageUrl;/*** 是否已加载图片*/boolean hasLoaded = false;public ImageProxy(String imageUrl) {this.imageUrl = imageUrl;}@Overridepublic void paint() {if (realImage != null) {// 有图片,则直接绘图realImage.paint();} else {// 没有图片,则先显示加载中的信息,再去加载并绘制图片System.out.println("Loading CD cover, please wait...");loadAndPaint();}}/*** 加载并绘制图片*/private void loadAndPaint() {if (hasLoaded) {return;}hasLoaded = true;// 加载图片是一个比较耗时的操作,为了避免程序阻塞,采用异步处理new Thread(new Runnable() {@Overridepublic void run() {realImage = new RealImage(imageUrl, "CD Cover");// 加载完后,再进行绘图realImage.paint();}}).start();}
}

(4)使用图片代理进行绘图

public class Test {public static void main(String[] args) throws InterruptedException {// 图片代理ImageProxy imageProxy = new ImageProxy("https://www.jingqueyimu.com/images/xxx.jpg");// 使用图片代理进行绘图System.out.println("首次绘图:");imageProxy.paint();Thread.sleep(3000);System.out.println("再次绘图:");imageProxy.paint();}
}

四、Java 动态代理

1、创建主题接口

/*** 主题接口*/
public interface Subject {/*** 请求主题执行某种动作*/void request();
}

2、创建真实主题(被代理类),并继承主题接口

/*** 真正做事的真实主题*/
public class RealSubject implements Subject {@Overridepublic void request() {System.out.println("RealSubject do something...");}
}

3、使用 Java 动态代理,代理真实主题

public class Test {public static void main(String[] args) {// 真实主题(被代理类)Subject realSubject = new RealSubject();// 调用处理器InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 代理实例的方法被调用时,最终会执行该方法System.out.println("InvocationHandler start to invoke...");// do something...// 调用真实主题(被代理类)的方法method.invoke(realSubject, args);// do something...return null;}};// 使用 Proxy 创建代理Subject subjectProxy = (Subject) Proxy.newProxyInstance(realSubject.getClass().getClassLoader(), realSubject.getClass().getInterfaces(), handler);// 通过代理发起请求subjectProxy.request();}
}

《Head First 设计模式》:代理模式相关推荐

  1. Python设计模式-代理模式

    Python设计模式-代理模式 基于Python3.5.2,代码如下 #coding:utf-8info_struct = dict() info_struct["addr"] = ...

  2. Java设计模式(代理模式-模板方法模式-命令模式)

    Java设计模式Ⅴ 1.代理模式 1.1 代理模式概述 1.2 静态代理 1.2.1 静态代理概述 1.2.2 代码理解 1.3 动态代理之JDK代理 1.3.1 动态代理之JDK代理概述 1.3.2 ...

  3. 设计模式——代理模式

    设计模式--代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能 ...

  4. 23种设计模式----------代理模式(一)

    代理模式也叫委托模式. 代理模式定义:对其他对象提供一种代理从而控制对这个对象的访问.就是,代理类 代理 被代理类,来执行被代理类里的方法. 一般情况下,代理模式化有三个角色. 1,抽象的主题类(或者 ...

  5. java设计模式代理模式_Java中的代理设计模式

    java设计模式代理模式 代理对象或代理对象为另一个对象提供占位符,以控制对该对象的访问. 代理充当原始对象的轻量级版本或简化版本. 它支持与原始对象相同的操作,但可以将那些请求委托给原始对象以实现它 ...

  6. 第四章 Caché 设计模式 代理模式

    文章目录 第四章 Caché 设计模式 代理模式 定义 类型 使用场景 优点 缺点 结构图 完整示例 抽象主题类 真实主题类 代理类 对象类 调用 思考 第四章 Caché 设计模式 代理模式 定义 ...

  7. Android常见设计模式——代理模式(Proxy Pattern)(二)

    文章目录 1. 前言 2. 远程代理(Remote Proxy) 3. 后记 1. 前言 在上篇Android常见设计模式--代理模式(Proxy Pattern)中基本上知道了什么是代理模式,以及对 ...

  8. sheng的学习笔记-设计模式-代理模式

    原理图: 代理模式的定义:由于某些原因需要给某对象提供一个代理以控制对该对象的访问.这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介. 至少在以下集中情况下可以用 ...

  9. 设计模式-代理模式(Proxy Pattern)

    设计模式-代理模式(Proxy Pattern) 文章目录 设计模式-代理模式(Proxy Pattern) 一.定义 二.概念解释 三.场景 四.实现 1.类图 2.代码实现 五.小结 六.动态代理 ...

  10. 简说设计模式——代理模式

    一.什么是代理模式 关于代理模式,我们听到的见到的最多的可能就是静态代理.动态代理之类的,当然还有大家都知道的Spring Aop,这里我们先不谈这些个代理,先说个简单的例子.游戏代练应该都听说过,许 ...

最新文章

  1. Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器绑定)
  2. 计算机软件及应用stata,蒙特卡洛模拟及其Stata应用实现
  3. Netapp日志出现auth.dc.trace.DCConnection.errorMsg:error报错
  4. Jenkins pipeline job 根据参数动态获取触发事件的分支
  5. Android 应用开发(17)---应用权限
  6. 多次面试美团后,我整理了这几个必备的技术栈!
  7. python itchat 无法登录_项目分享|5步教你用Python制作朋友圈个性签名
  8. 当稳定币遇上BCH,将会擦出什么样的火花?
  9. VS2010打开项目时弹出错误提示。。。VisualStudio\10.0\ActivityLog.
  10. “公益AI之星”挑战赛-新冠疫情相似句对判定大赛
  11. IDEA HTML 动态访问本地图片加载失败
  12. 易语言 mysql操作_易语言数据库应用手册
  13. 2022广东省安全员A证第三批(主要负责人)特种作业证考试题库及模拟考试
  14. 什么是a站、b站、c站、d站、e站、f站、g站、h站、i站、j站、k站、l站、m站、n站?00后的世界我不懂!
  15. salt同步配置文件
  16. 学习AngularJS摘抄的笔记,方便以后查看(摘自菜鸟教程)
  17. CDA学习笔记--EXCEL篇
  18. 四川高考成绩位次查询2021,211大学2021年四川录取分数线及位次排名
  19. 【汽车应用处理器】DRA770PJGACDQ1、TDA4VM88TGBALFR功能应用
  20. 滴滴助力 2020 中国开源年会 暨 阿帕奇中国路演

热门文章

  1. 春运路上:乘警的样子
  2. 第七章 数组成绩汇总
  3. 易优cms if 条件判断标签使用方法
  4. 【压力面试的应对策略】
  5. 当爬虫工程师需要学习什么
  6. 模拟MIC和数字MIC
  7. Python 与数据库交互的封装(MySQL,SQLServer,SQLite)
  8. 杭电oj —— 2037(贪心算法)
  9. 【以压缩文件方式打开文件失败】解决办法
  10. A Survey on Transfer Learning 论文阅读笔记与总结