实例讲解Java设计模式编程中如何运用代理模式
定义:
Provide a surrogate or placeholder for another object to control access to it.
为其他对象一种代理以控制对这个对象的访问。
一般描述:
一般包含的三个角色:抽象主题、具体主题、代理主题。
- 抽象主题:是一个抽象类或接口,是一个普通的业务类型定义。
- 具体主题:业务逻辑的具体执行者
- 代理角色:负责对真是角色的应用,把所有抽象主题类定义的方法限制委托给真实主题角色实现。
通用类图:
通用代码:
package Proxy; //抽象主题类: public interface Subject { public void doSomething(); } package Proxy; //具体主题类 public class RealSubject implements Subject{ @Override public void doSomething() { System.out.println("业务逻辑..."); } } package Proxy; //代理主题类 public class Proxy implements Subject{ private Subject sub = null; @Override public void doSomething() { this.sub.doSomething(); } public Proxy(Subject sub){ this.sub = sub; } } package Proxy; //客户端 public class Client { public static void main(String[] args) { Subject realsub = new RealSubject(); Subject proxy = new Proxy(realsub); proxy.doSomething(); } }
优点:
1. 职责清晰
2. 高扩展
代理模式的扩展:
普通代理:
具体主题类对高层透明,在代理主题类中构造具体主题类
代码实现:
package GeneralProxy; public interface Subject { public void doSomething(); } package GeneralProxy; public class RealSubject implements Subject{ private String name = null; @Override public void doSomething() { System.out.println(this.name + "被代理,正在执行业务逻辑..."); } public RealSubject(Subject proxy,String name) throws Exception{ if(proxy == null){ throw new Exception("无法创建被代理对象"); }else{ this.name = name; } } } package GeneralProxy; public class Proxy implements Subject{ private Subject realsub = null; public Proxy(String name) { try { realsub = new RealSubject(this, name); } catch (Exception e) { e.printStackTrace(); } } public void doSomething() { realsub.doSomething(); } } package GeneralProxy; public class Client { public static void main(String[] args) { //普通代理 Subject proxy = new Proxy("张三"); proxy.doSomethaing(); } }
强制代理:
必须通过访问具体主题类获取代理主题类的对象,然后用代理主题类控制访问
代码实现:
package MustProxy; public interface Subject { public void doSomething(); public Subject getProxy(); } package MustProxy; public class RealSubject implements Subject{ private String name = null; private Subject proxy = null; @Override public void doSomething() { if(isProxy()){ System.out.println(this.name + "被代理,正在执行业务逻辑..."); }else{ System.out.println("请先访问代理..."); } } public RealSubject(String name) { this.name = name; } public Subject getProxy() { proxy = new Proxy(this); return this.proxy; } private boolean isProxy(){ if(this.proxy == null){ return false; }else{ return true; } } } package MustProxy; public class Proxy implements Subject{ private Subject realSub = null; public Proxy(Subject realSub) { this.realSub = realSub; } public void doSomething() { this.realSub.doSomething(); } public Subject getProxy() { return this; } } package MustProxy; public class Client { public static void main(String[] args) { Subject realSub = new RealSubject("张三"); realSub.doSomething(); Subject proxy = realSub.getProxy(); proxy.doSomething(); } }
应用场景
现实世界中,秘书就相当于一个代理,老板开会,那么通知员工开会时间、布置会场、会后整理会场等等开会相关工作就可以交给秘书做,老板就只需要开会就行了,不需要亲自做那些事。同理,在我们程序设计中也可使用代理模式来将由一系列无关逻辑组合在一起的代码进行解耦合,比如业务代码中的日志代码就可以在代理中进行。Spring的AOP就是典型的动态代理应用。
代理模式的应用形式
(1)远程代理(Remote Proxy) -可以隐藏一个对象存在于不同地址空间的事实。也使得客户端可以访问在远程机器上的对象,远程机器可能具有更好的计算性能与处理速度,可以快速响应并处理客户端请求。
(2)虚拟代理(Virtual Proxy) – 允许内存开销较大的对象在需要的时候创建。只有我们真正需要这个对象的时候才创建。
(3)写入时复制代理(Copy-On-Write Proxy) – 用来控制对象的复制,方法是延迟对象的复制,直到客户真的需要为止。是虚拟代理的一个变体。
(4)保护代理(Protection (Access)Proxy) – 为不同的客户提供不同级别的目标对象访问权限
(5)缓存代理(Cache Proxy) – 为开销大的运算结果提供暂时存储,它允许多个客户共享结果,以减少计算或网络延迟。
(6)防火墙代理(Firewall Proxy) – 控制网络资源的访问,保护主题免于恶意客户的侵害。
(7)同步代理(SynchronizationProxy) – 在多线程的情况下为主题提供安全的访问。
(8)智能引用代理(Smart ReferenceProxy) - 当一个对象被引用时,提供一些额外的操作,比如将对此对象调用的次数记录下来等。
(9)复杂隐藏代理(Complexity HidingProxy) – 用来隐藏一个类的复杂集合的复杂度,并进行访问控制。有时候也称为外观代理(Façade Proxy),这不难理解。复杂隐藏代理和外观模式是不一样的,因为代理控制访问,而外观模式是不一样的,因为代理控制访问,而外观模式只提供另一组接口。