作用:为对象提供一种代理以控制对这个对象的访问。
示例-代理模式:
名称 |
说明 |
Printer |
表示命名的打印机类(本人) |
Printable |
Printer和PrinterProxy共享的接口 |
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 Pattern的Proxy参与者和RealSubject参与者两者的接口并没有差异(也即具备穿透性)
Decorator Pattern跟Proxy Pattern的实现模式很相似,但是目的却不同。前者是为了新增功能,后者则是注重代替“本人”进行作业,以减少“本人”存取操作,或者延迟“本人”实例化时间。