《Head First 设计模式》:代理模式
正文
一、定义
代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问。
要点:
- 代理模式为一个对象创建了代理对象,让代理对象控制对该对象的访问。被代理的对象可以是远程的对象、创建开销大的对象或者需要安全控制的对象。
- 代理类型:远程代理、虚拟代理、保护代理等。
- 远程代理:控制访问远程对象。
- 虚拟代理:控制访问创建开销大的资源。
- 保护代理:基于权限控制对资源的访问。
二、实现步骤
1、创建主题接口
/**
* 主题接口
*/
public interface Subject {
/**
* 请求主题执行某种动作
*/
void request();
}
2、创建真实主题(被代理类),并继承主题接口
真实主题是真正做事的主题对象。
/**
* 真正做事的真实主题(被代理类)
*/
public class RealSubject implements Subject {
@Override
public void request() {
System.out.println("RealSubject do something...");
}
}
3、创建主题代理(代理类),并继承主题接口
主题代理持有真正做事的真实主题,并控制对真实主题的访问。
/**
* 主题代理(代理类)
*/
public class SubjectProxy implements Subject {
/**
* 持有真实主题
*/
RealSubject realSubject;
@Override
public 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);
}
@Override
public 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;
}
@Override
public 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() {
@Override
public 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 {
@Override
public 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() {
@Override
public 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 设计模式》:代理模式的更多相关文章
- 9. 星际争霸之php设计模式--代理模式
题记==============================================================================本php设计模式专辑来源于博客(jymo ...
- C++设计模式——代理模式
前言 青春总是那样,逝去了才开始回味:大学生活也是在不经意间就溜走了,现在上班的时候,偶尔还会怀念大学时,大家在一起玩游戏的时光.大学喜欢玩游戏,但是可悲的校园网,速度能把人逼疯了:还好,后来搞了一个 ...
- PHP设计模式-代理模式
概念理解: 代理模式,是对简单处理程序(或指针)的增强,用于引用一个对象:这个指针被代理对象取代,代理对象位于客户端和真实程序之间,指针有一个可被多个目标利用的钩子. 参与者: client(参与者) ...
- Java设计模式-代理模式之动态代理(附源代码分析)
Java设计模式-代理模式之动态代理(附源代码分析) 动态代理概念及类图 上一篇中介绍了静态代理,动态代理跟静态代理一个最大的差别就是:动态代理是在执行时刻动态的创建出代理类及其对象. 上篇中的静态代 ...
- 浅谈Python设计模式 - 代理模式
声明:本系列文章主要参考<精通Python设计模式>一书,并且参考一些资料,结合自己的一些看法来总结而来. 一.在某些应用中,我们想要在访问某个对象之前执行一个或者多个重要的操作,例如,访 ...
- Java 之 设计模式——代理模式
设计模式——代理模式 一.概述 1.代理模式 (1)真实对象:被代理的对象 (2)代理对象:代理真实对象的 (3)代理模式:代理对象代理真实对象,达到增强真实对象功能的目的 二.实现方式 1.静态代理 ...
- [Head First设计模式]抢票中的设计模式——代理模式
系列文章 [Head First设计模式]山西面馆中的设计模式——装饰者模式 [Head First设计模式]山西面馆中的设计模式——观察者模式 [Head First设计模式]山西面馆中的设计模式— ...
- JAVA 设计模式 代理模式
用途 代理模式 (Proxy) 为其他对象提供一种代理以控制对这个对象的访问. 代理模式是一种结构型模式. 结构
- Java设计模式 - 代理模式
1.什么是代理模式: 为另一个对象提供一个替身或占位符以访问这个对象. 2.代理模式有什么好处: (1)延迟加载 当你需要从网络上面查看一张很大的图片时,你可以使用代理模式先查看它的缩略图看是否是自己 ...
- 深入浅出设计模式——代理模式(Proxy Pattern)
模式动机在某些情况下,一个客户不想或者不能直接引用一个对象,此时可以通过一个称之为“代理”的第三者来实现间接引用.代理对象可以在客户端和目标对象之间起到中介的作用,并且可以通过代理对象去掉客户不能看到 ...
随机推荐
- Cassandra社区是怎么测试4.0的
点击查看活动录像,获取更多技术细节. Cassandra社区是怎么测试4.0的 Cassandra 4.0的目标就是成为史上最稳定的版本.为了达到这个目的,我们需要用很多方法和工具进行测试.我今天主要 ...
- [PyTorch 学习笔记] 3.3 池化层、线性层和激活函数层
本章代码:https://github.com/zhangxiann/PyTorch_Practice/blob/master/lesson3/nn_layers_others.py 这篇文章主要介绍 ...
- 由浅入深理解 IOC 和 DI
目录 由浅入深理解 IOC 和 DI 开闭原则 OCP(Open Closed Principle) 面向抽象编程 逐步理解实现 IOC 和 DI 的过程(LOL Demo 示例) 比较尴尬的编写程序 ...
- composer安装依赖包时,php内存分配不足
Fatal error: Allowed memory size of 1610612736 bytes exhausted (tried to allocate 4096 bytes) in pha ...
- python爬取B站视频弹幕分析并制作词云
1.分析网页 视频地址: www.bilibili.com/video/BV19E… 本身博主同时也是一名up主,虽然已经断更好久了,但是不妨碍我爬取弹幕信息来分析呀. 这次我选取的是自己 唯一的爆款 ...
- Python数据清洗:提取爬虫文本中的电话号码
步骤索引 效果展示 注意事项 代码 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识. ...
- 【JAVA】生成一个32位的随机数。防止重复,保留唯一性
作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 微博:http://weibo.com/mcxiaobing import ...
- vue打包之后找不到图片路径,打包项目时,dist文件夹内部分图片找不到
1.打包项目时,会默认把存放在public内的小于4k的图片转换成base64,作为内联样式. 可以在vue.config.js中修改默认大小,在chainWepack:config=>{}中添 ...
- playable
探索TimelinePlayableAPI,让Timeline为所欲为 https://blog.csdn.net/qq826364410/article/details/80534892 Playa ...
- ORA-01033错误解决方案-九五小庞
Microsoft Windows [版本 6.3.9600](c) 2013 Microsoft Corporation.保留所有权利. C:\Users\Administrator>sqlp ...