一 简介
代理模式(Proxy pattern
):属于结构型设计模式,为另一个对象提供一个替身或占位符以控制对这个对象的访问。
二 意图
代理控制着对于原对象的访问,并允许在将请求提交给对象前后进行一些处理。
三 结构
- Subject: 抽象主题角色 定义了被代理角色和代理角色的共同接口或者抽象类
- RealSubject: 被代理角色 实现或者继承抽象主题角色,定义实现具体业务逻辑的实现
- Proxy: 代理角色 实现或者继承抽象主题角色,持有被代理角色的引用,控制和限制被代理角色的实现,并且拥有自己的处理方法(预处理和善后)
四 代码实现
以下用娱乐圈中明星与经纪人的关系来更具体地解释代理模式。
经纪人的角色就相当于一个代理,要找到明星必须得先经过他的经纪人,经纪人负责给明星接洽各种商业活动,而明星只需要专注于拍电影、唱歌就好了。这就是为什么要用到代理的原因,抛开其他繁琐的事务,专注被代理人的业务逻辑,减轻被代理人的负担。
抽象主题角色: Subject
public interface Subject {
public void filming ();
}
被代理角色: RealSubject
public class Star implements Subject {
@Override
public void filming() {
System.out.println(getClass().getSimpleName() + ":经纪人接了一部电影,我主演");
}
}
代理角色:Proxy
public class Agent implements Subject {
private Subject star;
public Agent(Subject star) {
this.star = star;
}
@Override
public void filming() {
System.out.println(getClass().getSimpleName() + ":剧本很好,这部电影接下了");
star.filming();
}
}
客户类调用:
public class Client {
public static void main(String[] args) {
Subject star = new Star();
Subject proxy = new Agent(star);
proxy.filming();
}
}
表面上是调用了代理的方法,实际的执行者其实是被代理角色 Star:
Agent:剧本很好,这部电影接下了
Star:经经纪人接了一部电影,我主演
五 总结
优点:
- 良好的扩展性。修改被代理角色并不影响调用者使用代理,对于调用者,被代理角色是透明的。
- 降低耦合度。代理角色协调调用者和被代理角色,被代理角色只需实现本身关心的业务,非自己本职的业务通过代理处理和隔离。
缺点:
- 增加了代理类,实现需要经过代理,因此请求速度会变慢。
使用场景:
- 延迟初始化(虚拟代理): 如果有一个偶尔使用的重量级服务对象,一直保持该对象运行会消耗系统资源时,可使用代理模式。
- 访问控制(保护代理): 如果只希望特定客户端使用服务对象,这里的对象可以是操作系统中非常重要的部分,而客户端则是各种已启动的程序(包括恶意程序),此时可使用代理模式。
- 本地执行远程服务(远程代理): 适用于服务对象位于远程服务器上的情形。
- 记录日志请求(日志记录代理): 适用于当需要保存对于服务对象的请求历史记录时。
- 缓存请求结果(缓存代理): 适用于需要缓存客户请求结果并对缓存生命周期进行管理时, 特别是当返回结果的体积非常大时。
- 智能引用: 可在没有客户端使用某个重量级对象时立即销毁该对象。