1、引入
代理模式,顾名思义是委托代理人来进行某些工作的模式。
在现实生活中,一般在委托人过忙时,会寻找代理人帮忙处理,而代理人虽然可以处理部分事务,但任然存在着不能解决的问题,这时候又要交回委托人处理。在代理模式中也是如此。
代理模式由以下几部分组成:
- 被代理者
- 代理者
- 使用者
2、示例
实现以下功能:被代理者为一台启动慢的打印机,使用者有时只需要获取或设置打印机名字,有时需要用打印机打印东西。
2.1、被代理者打印机
首先有接口:
public interface Printable {
public abstract void setPrinterName(String name);
public abstract String getPrinterName();
public abstract void print(String str);
}
打印机实现类:
public class Printer implements Printable{
private String name;
public Printer(String name) {
this.name=name;
heavyJob("Printer实例生成中");
}
@Override
public void setPrinterName(String name) {
this.name=name;
}
@Override
public String getPrinterName() {
return name;
}
@Override
public void print(String str) {
System.out.println("========="+name+"=======");
System.out.println(str);
}
private void heavyJob(String msg) {
System.out.println(msg);
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(".");
}
System.out.println("end");
}
}
2.2、代理类
实现代理类,可以替打印机完成名字获取与设置功能
public class PrinterProxy implements Printable{
private String name;
private Printer real;
public PrinterProxy() {
}
public PrinterProxy(String name) {
this.name = name;
}
@Override
public void setPrinterName(String name) {
if (real != null) {
real.setPrinterName(name);
}
this.name=name;
}
@Override
public String getPrinterName() {
return name;
}
@Override
public void print(String str) {
realize();
real.print(str);
}
private synchronized void realize() {
if (real == null) {
real=new Printer(name);
}
}
}
2.3、测试
当获取和设置名字时,只需要创建代理对象即可;当真正需要打印时,代理对象内才会创建打印机实例。
public class Main {
public static void main(String[] args) {
PrinterProxy printerProxy = new PrinterProxy("Alice");
System.out.println("现在的名字是:"+printerProxy.getPrinterName()+".");
printerProxy.setPrinterName("Bob");
System.out.println("现在的名字是:"+printerProxy.getPrinterName()+".");
printerProxy.print("Hello");
}
}
运行结果:
3、tips
- 代理模式将被代理者和代理者的职责区分开了,各司其职,实现了解耦的功效,并且部分条件下能减少内存占用和运行速度。
- 代理模式相当于在被代理者和使用者之间加了一层,多出来的这一层可以起到保护内层、方便拓展等功能。
- 被代理类和代理类实现了相同的接口,因此在外界使用者看了他俩是一样的。