Proxy是代理人的意思,指的是代替别人进行工作的人。当不一定需要本人亲自去做的工作的时候,就可以寻找代理人去完成。
但在代理模式中,往往是相反的,通常是代理人碰到工作,就交给被代理的对象去完成,代理人只完成一些准备工作或者收尾工作。
如果读者了解过spring框架的话,就会知道aop也就是面向切面编程其实运用的就是动态代理模式,这可以让被代理的对象专注于完成自己的本职工作,而代理对象可以进行工作前的日志记录,时间计算,在工作之后进行日志记录,收尾工作等附加的功能,需要正式做工作的时候就交给被代理去做。就像插了两个刀到这个被代理的对象前后。所以形象的叫做面向切面编程。
关于动态代理模式和静态代理模式,感兴趣的读者可以参考笔者的另一篇博文:
Java动态代理与静态代理http://www.jianshu.com/p/b5e340ec9551
我们会实现一个打印机,向屏幕打印一串字符串,然后交给代理对象去完成这个功能。
首先看一下类图:
image.png
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 < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
System.out.print(".");
}
System.out.println("结束。");
}
}
Printable接口:
package Proxy;
public interface Printable {
public abstract void setPrinterName(String name);
public abstract String getPrinterName();
public abstract void print(String string);
}
PrinterProxy类,利用反射机制,动态生成被代理的对象,并且延迟初始化到需要调用它的时候再初始化
package Proxy;
public class PrinterProxy implements Printable {
private String name; // 名字
private Printable real; // “本人”
private String className; // “本人”的类名
public PrinterProxy(String name, String className) { // 构造函数
this.name = name;
this.className = className;
}
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) {
try {
real = (Printable)Class.forName(className).newInstance();
real.setPrinterName(name);
} catch (ClassNotFoundException e) {
System.err.println("没有找到 " + className + " 类。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
Main类测试:
package Proxy;
public class Main {
public static void main(String[] args) {
Printable p = new PrinterProxy("Alice", "Proxy.Printer");
System.out.println("现在的名字是" + p.getPrinterName() + "。");
p.setPrinterName("Bob");
System.out.println("现在的名字是" + p.getPrinterName() + "。");
p.print("Hello, world.");
}
}
运行结果:
image.png
代理模式中的角色:
代理模式的类图:
image.png