在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。
Printer.java
package com.test.dp.Proxy.Sample;
//表示带名字的打印机的类(本人)
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 < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.print(".");
}
System.out.println("结束。");
}
}
Printable.java
package com.test.dp.Proxy.Sample;
//Printer和PrinterProxy的共同接口
public interface Printable {
public abstract void setPrinterName(String name); // 设置名字
public abstract String getPrinterName(); // 获取名字
public abstract void print(String string); // 显示文字(打印输出)
}
PrinterProxy.java
package com.test.dp.Proxy.Sample;
//表示带名字的打印机的类(代理人)
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);
}
}
}
Main.java
package com.test.dp.Proxy.Sample;
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, world.");
}
}
执行结果:
现在的名字是Alice。
现在的名字是Bob。
正在生成Printer的实例(Bob).....结束。
=== Bob ===
Hello, world.
总结:
应用实例:1、Windows 里面的快捷方式。2、猪八戒去找高翠兰结果是孙悟空变的,可以这样理解:把高翠兰的外貌抽象出来,高翠兰本人和孙悟空都实现了这个接口,猪八戒访问高翠兰的时候看不出来这个是孙悟空,所以说孙悟空是高翠兰代理类。3、买火车票不一定在火车站买,也可以去代售点。4、一张支票或银行存单是账户中资金的代理。支票在市场交易中用来代替现金,并提供对签发人账号上资金的控制。5、spring aop。
优点:1、职责清晰。2、高扩展性。3、智能化。
缺点:1、由于在客户端和真实主题之间增加了代理对象,因此有些类型的代理模式可能会造成请求的处理速度变慢。2、实现代理模式需要额外的工作,有些代理模式的实现非常复杂。
使用场景:按职责来划分,通常有以下使用场景:1、远程代理。2、虚拟代理。3、Copy-on-Write 代理。4、保护(Protect or Access)代理。5、Cache代理。6、防火墙(Firewall)代理。7、同步化(Synchronization)代理。8、智能引用(Smart Reference)代理。
注意事项:1、和适配器模式的区别:适配器模式主要改变所考虑对象的接口,而代理模式不能改变所代理类的接口。2、和装饰器模式的区别:装饰器模式为了增强功能,而代理模式是为了加以控制。