Proxy Pattern-署理模式

Proxy Pattern-代理模式

作用:为对象提供一种代理以控制对这个对象的访问。

示例-代理模式:

名称

说明

Printer

表示命名的打印机类(本人)

Printable

PrinterPrinterProxy共享的接口

PrinterProxy

表示命名的打印机的类(代理)

Main

测试类

 类图查看图片附件:类图-Proxy_1

//------------------------------------------ Printable---------------------------

package proxy;

public interface Printable{

    public abstract void setPrinterName(String name);//命名

    public abstract String getPrinterName();//取得名称

    public abstract void print(String string);    //输出字符串(打印)

}

//------------------------------------------ Printer---------------------------

package proxy;

public class Printer implements Printable{

    private String name;

    public Printer(){

       heavyJob("正在产生Printer的实例对象");

    }

    public Printer(String name){

        this.name = name;

       heavyJob("正在产生Printer的对象实例(" + name + ")");

    }

    public void setPrinterName(String name){

       this.name = name;

    }

    public String getPrinterName(){

       return name;

    }

    public void print(String String){

       System.out.println("==="+ name + " ===");

       System.out.println(String);

    }

  private void heavyJob(String msg){

        System.out.print(msg);

        for(int i = 0; i < 10; i++){

               try{

                  Thread.sleep(500);  

               } catch (InterruptedException e) {

               }

              

System.out.print(".");

        }

        System.out.println("完成");

  }

} //------------------------------------------ PrinterProxy ---------------------------

package proxy;

public class PrinterProxy implements Printable {

    private String name;//命名

    private Printer real;//"本人"

    public PrinterProxy(){

    }

    public PrinterProxy(String name){//构造函数

       this.name = name;

    }  

    public synchronized void setPrinterName(String name){//命名

           if (real != null){

              real.setPrinterName(name);//本人也要命名

           }

           this.name = name;

    }

    public String getPrinterName(){//取得名称

       return name; 

    }

    public void print(String String){//输出

           realize();

           real.print(String);

    }

    private synchronized void realize(){ //产生本人

       if (real == null) {

           real = new Printer(name);

       }  

    }

   

}

//------------------------------------------测试类---------------------------

package proxy;

public class Main{

    public static void main(String[] args){

       Printable p = new PrinterProxy("Alice");

       System.out.println("现在的名称是" + p.getPrinterName() + ".");

       p.setPrinterName("BOb");

       System.out.println("现在的名称是" + p.getPrinterName() + ".");

       p.print("Hello,CCF~~"); 

    }

}

解析:

PrinterProxy类和Printer类是一视同仁的,所以例外定义了Printable接口。设置名称(getName())、获得名称(setName())这样简单的任务就又代理来完成,需要打印(print),这样费时的任务就又本人来做,其中heavyJob()就模拟了这个费时性。

所谓“代理”,就是代替那个“本人”来做事,即为:本人将不需要自己做的事情外包出去,但是,这个代理能力范围有限,如果超出能力范围,就由本人自己来完成任务。

以下是Adapter Pattern模式解析

代理模式参与者

Subject-主体)参与者规定对Proxy参与者和RealSubject参与者一视同仁的接口。因为已经有Subject参与者所以Client参与者就不需要去注意Proxy参与者与RealSubject参与者之间的差异,就如实例中的Printable接口一样。

Proxy-(代理)参与者,Proxy会尽量处理Client参与者的要求,当自己无法单独处理时,就会将工作交给RealSubject参与者。

RealSubject-(实际主体)参与者,就是“本人”角色,它和Proxy都实现了Subject参与者规定的接口

Client-接口调用参与者,在实例中是测试类充当了这个角色。

协作过程:代理根据其种类,在适当的时候向RealSubject转发请求。

代理模式实现类图见图片附件:类图-Proxy_2

模式分析:

代理模式给某一个对象提供一个代理对象,并由代理对象控制对源对象的引用。代理就是一个人或一个机构代表另一个人或者一个机构采取行动。某些情况下,客户不想或者不能够直接引用一个对象,代理对象可以在客户和目标对象直接起到中介的作用。客户端分辨不出代理主题对象与真实主题对象。代理模式可以并不知道真正的被代理对象,而仅仅持有一个被代理对象的接口,这时候代理对象不能够创建被代理对象,被代理对象必须有系统的其他角色代为创建并传入。

适用性:

<1> Remote Proxy可以隐藏一个对象存在于不同地址空间的事实

<2> Virtual Proxy可以进行最优化,例如根据要求创建对象,这样利用代理提高了处理速度。     

<3> Protection proxy等允许在访问一个对象时有一些附件的内务处理。

比较:

Adaper Pattern的功能是连接两个接口有差异的对象,Proxy PatternProxy参与者和RealSubject参与者两者的接口并没有差异(也即具备穿透性)

Decorator PatternProxy Pattern的实现模式很相似,但是目的却不同。前者是为了新增功能,后者则是注重代替“本人”进行作业,以减少“本人”存取操作,或者延迟“本人”实例化时间。