代理模式
大约 2 分钟
意图
代理模式(Proxy)是指实现了一个类「代替」另外一个类的功能,它能控制对于原对象的访问。
图片来自:https://refactoringguru.cn/design-patterns/proxy
真实世界
在《大话设计模式》中有这样一个故事,「A 男孩」喜欢 「C 女孩」,但是由于羞耻不敢于表达。于是 「A 男孩」就“拜托”与「C 女孩」同班的「B 男孩」帮助他。「A 男孩」买了很多礼物,委托「B 男孩」去送给「C 女孩」。由于每次都是「C 女孩」与「B 男孩」相处,而且「C 女孩」每次都从「B 男孩」手里接过礼物,最后两个人在一起了。
- 追求者「A 男孩」
- 被追求者「C 女孩」
- 代理「B 男孩」
所以他们三个人之间的关系是追求者「A 男孩」委托 代理「B 男孩」,通过代理给被追求者「C 女孩」送礼物。而被追求者「C 女孩」只与代理「B 男孩」进行接触。也就是说代理「B 男孩」代表了追求者「A 男孩」的 送礼物功能,被追求者「C 女孩」只与代理「B 男孩」接触就收到了礼物。
- 信用卡是银行账户的代理,而银行账户则是一大捆现金的代理。它们都可以实现相同的支付功能。
- windows里的快捷方式。
UML
- ServiceInterface:定义了 Service 和 Proxy 的共用操作
- Service:实现了操作逻辑
- Proxy:保存了 Service 的一个引用可以使得代理可以访问 Service,并提供一个与 Service 的接口相同的接口,这样就可以代替 Service。
实现
// 目标对象接口
interface Image {
void display();
}
// 目标对象实现
class RealImage implements Image {
private String fileName;
public RealImage(String fileName) {
this.fileName = fileName;
loadFromDisk(fileName);
}
private void loadFromDisk(String fileName) {
System.out.println("Loading " + fileName);
}
@Override
public void display() {
System.out.println("Displaying " + fileName);
}
}
// 代理类
class ProxyImage implements Image {
private RealImage realImage;
private String fileName;
public ProxyImage(String fileName) {
this.fileName = fileName;
}
// 延迟初始化
private void checkAndLoad() {
if (realImage == null) {
realImage = new RealImage(fileName);
}
}
@Override
public void display() {
checkAndLoad();
realImage.display();
}
}
// 客户端代码
public class ProxyPatternDemo {
public static void main(String[] args) {
Image image = new ProxyImage("test_image.png");
// 显示图片,此时代理对象会检查RealImage是否已经加载,如果没有则加载
image.display();
// 再次显示图片,RealImage已经被加载,代理对象直接调用其display方法
image.display();
}
}