问题分析:
什么是代理模式呢?其实我们在生活中并不少见。对于程序员来说最常接触的莫过于代理上网了,连接大力服务器地址,就可以访问网络。
还有每天吃饭赶进度是常事,叫公司的同事帮忙带饭也是一种代理;如果你辞职老板不给你发工资,那么你还得请个律师帮你打官司,这也是一种代理。总之生活中无处不在。
代理的定义:
为其他对象提供一种代理以控制对这个对象的访问。简单点就是在不直接操作访问对象的的情况下,找一个代理访问该对象,就是自己不想搞,这个其他人帮你搞。
基本UML图:
具体问题UML类图:
抽象主题类Subject.java
package com.hust.staticProxy1; public abstract class Subject { public abstract void visit();//普通业务方法 }实现抽象主题的真正主题类RealSubject.java
package com.hust.staticProxy1; public class RealSubject extends Subject { public void visit() { System.out.println("Real Subject!"); } }代理类ProxySubject.java
package com.hust.staticProxy1; //代理类 public class ProxySubject extends Subject { private RealSubject mRealSubject;//把被代理对象作为成员变量 public ProxySubject(RealSubject mRealSubject){ this.mRealSubject=mRealSubject; } public void visit() { mRealSubject.visit();//调用被代理对象的逻辑方法 } }Client.java
package com.hust.staticProxy1; public class Client { /** * @param args */ public static void main(String[] args) { //实例化一个被代理对象 RealSubject mRealSubject=new RealSubject(); //用被代理对象构造一个代理对象 ProxySubject mProxySubject=new ProxySubject(mRealSubject); //调用代理对象的相关方法 mProxySubject.visit(); } }代理模式的简单实现:
诉讼接口类
package com.hust.staticProxy2; public interface LawSuit { //提交申请 void submit(); //进行举证 void burden(); //开始辩护 void defend(); //诉讼完成 void finish(); }具体诉讼人,就是被代理对象小明,就是他想做的事
package com.hust.staticProxy2; public class XiaoMing implements LawSuit {//被代理类,实现诉讼接口 public void submit() { // 老板欠小明工资,小明只好申请仲裁 System.out.println("老板欠小明工资,小明只好申请仲裁"); } public void burden() { //小明证据充足,不怕告不赢 System.out.println("这是合同书和过去一年的银行卡工资流水"); } public void defend() { // 铁证如山,辩护也没什么好说的 System.out.println("证据确凿!不需要早说些什么了!"); } public void finish() { // 结果也肯定的 System.out.println("诉讼成功,判决老板即日起七天内结算工资"); } }代理律师类:就是代理对象,小明让这个代理类完成诉讼流程
package com.hust.staticProxy2; //律师代理类 public class Lawyer implements LawSuit{ private LawSuit mLawSuit; public Lawyer(LawSuit mLawSuit){ this.mLawSuit=mLawSuit; } public void submit() { // 调用被代理类的方法 mLawSuit.submit(); } public void burden() { // 调用被代理类的方法 mLawSuit.burden(); } public void defend() { // 调用被代理类的方法 mLawSuit.defend(); } public void finish() { // 调用被代理类的方法 mLawSuit.finish(); } }客户端类
package com.hust.staticProxy2; public class ClientTest { /** * @param args */ public static void main(String[] args) { //构造被代理对象小明 LawSuit xiaoming=new XiaoMing(); //小明委托代理对象律师 Lawyer mLawyer=new Lawyer(xiaoming); //代理对象律师帮助小明提出诉讼申请 mLawyer.submit(); //代理对象律师进行举证 mLawyer.burden(); //代理对象律师代替小明进行辩护 mLawyer.defend(); //代理对象律师完成诉讼 mLawyer.finish(); } }输出:
老板欠小明工资,小明只好申请仲裁 这是合同书和过去一年的银行卡工资流水 证据确凿!不需要早说些什么了! 诉讼成功,判决老板即日起七天内结算工资
真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。
代理模式的一个好处就是对外部提供统一的接口方法,而代理类在接口中实现对真实类的附加操作行为,从而可以在不影响外部调用情况下,进行系统扩展。也就是说,我要修改真实角色的操作的时候,尽量不要修改他,而是在外部在“包”一层进行附加行为,即代理类。例如:接口A有一个接口方法operator(),真实角色:RealA实现接口A,则必须实现接口方法operator()。客户端Client调用接口A的接方法operator()。现在新需求来了,需要修改RealA中的operator()的操作行为。怎么办呢?如果修改RealA就会影响原有系统的稳定性,还要重新测试。这是就需要代理类实现附加行为操作。创建代理ProxyA实现接口A,并将真实对象RealA注入进来。ProxyA实现接口方法operator(),另外还可以增加附加行为,然后调用真实对象的operator()。从而达到了“对修改关闭,对扩展开放”,保证了系统的稳定性。我们看客户端Client调用仍是接口A的接口方法operator(),只不过实例变为了ProxyA类了而已。也就是说代理模式实现了ocp原则。
什么时候使用代理模式
当我们需要使用的对象很复杂或者需要很长时间去构造,这时就可以使用代理模式(Proxy)。例如:如果构建一个对象很耗费时间和计算机资源,代理模式(Proxy)允许我们控制这种情况,直到我们需要使用实际的对象。一个代理(Proxy)通常包含和将要使用的对象同样的方法,一旦开始使用这个对象,这些方法将通过代理(Proxy)传递给实际的对象。 一些可以使用代理模式(Proxy)的情况:
1,一个对象,比如一幅很大的图像,需要载入的时间很长。
2,一个需要很长时间才可以完成的计算结果,并且需要在它计算过程中显示中间结果
3,一个存在于远程计算机上的对象,需要通过网络载入这个远程对象则需要很长时间,特别是在网络传输高峰期。
4,一个对象只有有限的访问权限,代理模式(Proxy)可以验证用户的权限
代理模式(Proxy)也可以被用来区别一个对象实例的请求和实际的访问,例如:在程序初始化过程中可能建立多个对象,但并不都是马上使用,代理模式(Proxy)可以载入需要的真正的对象。这是一个需要载入和显示一幅很大的图像的程序,当程序启动时,就必须确定要显示的图像,但是实际的图像只能在完全载入后才可以显示!这时我们就可以使用代理模式(Proxy)。