代理模式的定义:
由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象不适合或者不能直接引用目标对象,代理对象作为访问对象和目标对象之间的中介。例如,买高铁票可以通过 12306 网站或者车票代售点购买而不是去车站。如找房子可以通过房屋中介完成。
代理模式的主要优点有:
- 代理对象在客户端与目标对象之间起到一个中介作用和保护目标对象的作用;
- 代理对象可以扩展目标对象的功能;
- 代理对象能将客户端与目标对象分离,在一定程度上降低了系统的耦合度,增加了程序的可扩展性
其主要缺点是:
- 代理模式会造成系统设计中类的数量增加
- 增加了系统的复杂度;
代理模式的结构
代理模式的主要角色如下。
- 抽象角色(Subject):通过接口或抽象类声明真实角色和代理角色实现的业务方法。
- 真实角色(RealSubject):实现抽象角色接口。实现了抽象角色中的具体业务,是代理对象所代表的真实对象,是最终要引用的对象。
- 代理角色(Proxy):是真实角色的代理,实现了与真实角色相同的接口,其内部含有对真实主题的引用,它可以访问、控制或扩展真实主题的功能。
如图所示:
代理模式的实现
例子:一个追求者(Pursuit)在追求MM(SchoolGirl),但是因为害羞,所以委托Proxy给MM送礼物(GiveGift接口)。追求者的业务委托Proxy实现。
追求者和Proxy都要实现的抽象角色(接口),追求者是真正实现者。
抽象角色:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:23
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public interface GiveGift {
void giveSomething();
}
真实角色追求者:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:24
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class Pursuit implements GiveGift {
public Pursuit(SchoolGirl girl) {
this.girl = girl;
}
@Override
public void giveSomething() {
System.out.println("送礼物给" + girl.getName());
}
private SchoolGirl girl;
}
代理角色Proxy:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:21
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class Proxy implements GiveGift {
public Proxy(SchoolGirl girl) {
pursuit = new Pursuit(girl);
}
@Override
public void giveSomething() {
pursuit.giveSomething();
}
private Pursuit pursuit;
}
追求的MM:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:19
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class SchoolGirl {
public SchoolGirl(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
}
客户端代码:
package proxy;
/**************************************************************************************************
@Copyright 2003-2022
@package proxy
@date 2022/2/3 22:28
@author qiao wei
@version 1.0
@brief
@history
*************************************************************************************************/
public class MainClass {
public static void main(String[] args) {
SchoolGirl girl = new SchoolGirl("李凌君");
Proxy proxyBoy = new Proxy(girl);
proxyBoy.giveSomething();
}
}
结果:
送礼物给李凌君
代理模式使用场景
- 远程代理,也就是为一个对象在不同的地址空间提供局部代表。这样可以隐藏一个对象存在于不同地址空间的事实。
- 虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。
- 安全代理,用来控制真实对象访问时的权限。
- 智能指引,是指当调用真实的对象时,代理处理另外一些事。