在真实对象执行某些操作前或操作后,附加一些额外的操作。
比如与房东签订租房合同这个操作,我们在执行这个操作前肯定需要看房,咨询问题等操作,而这些操作一般都是交给中介的。
以上就出现了三个角色:
除此之外,代理模式还可以延迟真实对象的产生时机,请求者一直都是与代理对象打交道,代理对象内部会关联一个真实对象,
只有真正需要用到真实对象时,才去创建,并调用其方法。比如示例程序就是展示了这一作用。
示例程序展示了使用打印机的过程,打印机有名称,以及“使用打印机”的方法
抽象打印机,表示了打印机的能力,用于实现真实对象与代理对象的一致性。
public interface Printable {
void setPrinterName(String name);
String getPrinterName();
void print(String string);
}
真实对象,打印机。真正干活的人,只有需要用到print方法的时候才会产生(延迟创建)
public class Printer implements Printable {
private String name;
public Printer() {
heavyJob("Printer的实例生成中");
}
public Printer(String name) {
this.name = name;
heavyJob("Printer的实例生成中(" + name + ")");
}
@Override
public void setPrinterName(String name) {
this.name = name;
}
@Override
public String getPrinterName() {
return name;
}
@Override
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) {
e.printStackTrace();
}
System.out.print(".");
}
System.out.println("结束。");
}
}
代理对象,PrintProxy也实现了抽象打印机的接口,所以与真实对象具有相同的能力(一致性),所以请求者只需要跟代理对象打交道即可,
这样在使用真实对象的操作前或操作后,都可以通过代理对象增加一些额外操作,以便扩展其能力。
public class PrinterProxy implements Printable {
private String name;
private Printer real;
public PrinterProxy() {
}
public PrinterProxy(String name) {
this.name = name;
}
@Override
public synchronized void setPrinterName(String name) {
if (real != null) {
real.setPrinterName(name);
}
this.name = name;
}
@Override
public String getPrinterName() {
return name;
}
@Override
public void print(String string) {
realize();
real.print(string);
}
private synchronized void realize() {
if (real == null) {
real = new Printer(name);
}
}
}
测试类
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!");
}
}
这里的代理模式和例子展示的功能,有点偏向于延迟真实对象的加载和调用,当没有真正使用打印机之前,无论是给打印机设置名称和获取名称,
其实都是在对打印机代理做出操作,先把名称放在打印机代理这里,等到真正使用打印机时,才把名称给到打印机,并使用打印机