设计模式之代理模式
简单理解一下代理模式
代理模式很简单,简单的来说代理模式就是一个在美国的人想买中国人的手机,但是人在异地这个时候就需要联系一个中国人,中国人买上手机以后在把手机给了美国人,这个中国人就可以理解为是代理人,也就是代理模式的大概流程
以下是代理模式的结构图(源网址:https://blog.csdn.net/lovelion/article/details/8227953)
代理模式主要分为三大部分
1.Subject(抽象主题角色)
它声明了真实主题和代理主题的共同接口,这样一来在任何使用真实主题的地方都可以使用代理主题,客户端通常需要针对抽象主题角色进行编程。
2.Proxy(代理主题角色)
它包含了对真实主题的引用,从而可以在任何时候操作真实主题对象;在代理主题角色中提供一个与真实主题角色相同的接口,以便在任何时候都可以替代真实主题;代理主题角色还可以控制对真实主题的使用,负责在需要的时候创建和删除真实主题对象,并对真实主题对象的使用加以约束。通常,在代理主题角色中,客户端在调用所引用的真实主题操作之前或之后还需要执行其他操作,而不仅仅是单纯调用真实主题对象中的操作。
3.RealSubject(代理主题角色)
它定义了代理角色所代表的真实对象,在真实主题角色中实现了真实的业务操作,客户端可以通过代理主题角色间接调用真实主题角色中定义的操作。
常用的代理模式
远程代理(Remote Proxy)
为一个位于不同的地址空间的对象提供一个本地的代理对象,这个不同的地址空间可以是在同一台主机中,也可是在另一台主机中,远程代理又称为大使(Ambassador)。
虚拟代理(Virtual Proxy)
如果需要创建一个资源消耗较大的对象,先创建一个消耗相对较小的对象来表示,真实对象只在需要时才会被真正创建。
保护代理(Protect Proxy)
控制对一个对象的访问,可以给不同的用户提供不同级别的使用权限。
缓冲代理(Cache Proxy)
为某一个目标操作的结果提供临时的存储空间,以便多个客户端可以共享这些结果。
智能引用代理(Smart Reference Proxy)
当一个对象被引用时,提供一些额外的操作,例如将对象被调用的次数记录下来等。
代理模式的应用场景
当无法或不想直接引用某个对象或访问某个对象存在困难时,可以通过代理对象来间接访问。使用代理模式主要有两个目的:一是保护目标对象,二是增强目标对象。
前面分析了代理模式的结构与特点,现在来分析以下的应用场景。
远程代理,这种方式通常是为了隐藏目标对象存在于不同地址空间的事实,方便客户端访问。例如,用户申请某些网盘空间时,会在用户的文件系统中建立一个虚拟的硬盘,用户访问虚拟硬盘时实际访问的是网盘空间。
虚拟代理,这种方式通常用于要创建的目标对象开销很大时。例如,下载一幅很大的图像需要很长时间,因某种计算比较复杂而短时间无法完成,这时可以先用小比例的虚拟代理替换真实的对象,消除用户对服务器慢的感觉。
安全代理,这种方式通常用于控制不同种类客户对真实对象的访问权限。
智能指引,主要用于调用目标对象时,代理附加一些额外的处理功能。例如,增加计算真实对象的引用次数的功能,这样当该对象没有被引用时,就可以自动释放它。
延迟加载,指为了提高系统的性能,延迟对目标的加载。例如,Hibernate 中就存在属性的延迟加载和关联表的延时加载。
代码走一波结束
public class Dalimoshi {
public static void main(String[] args) {
new SgProxy().Request();
}
}
interface Subject{
void Request();
}
//真实主题
class WySpecialty implements Subject{
public void Request() {
System.out.println("婺源特产公司的X特产");
System.out.println("婺源特产公司的Y特产");
System.out.println("婺源特产公司的Z特产");
}
}
//代理
class SgProxy implements Subject {
private WySpecialty wySpecialty;
public void Request() {
if (wySpecialty == null){
wySpecialty = new WySpecialty();
}
Request1();
new WySpecialty().Request();
Request2();
}
public void Request1() {
System.out.println("准备去“天街e角”公司");
System.out.println("看到了婺源特产公司的员工风貌");
System.out.println("还看到了:");
}
public void Request2() {
System.out.println("访问完毕,特产不错");
}
}
代码运行结果:
准备去“天街e角”公司
看到了婺源特产公司的员工风貌
还看到了:
婺源特产公司的X特产
婺源特产公司的Y特产
婺源特产公司的Z特产
访问完毕,特产不错