一、Proxy模式
Proxy是“代理人”的意思,它指的是代替别人进行工作的人。当不一定需要本人亲自进行工作时,就可以寻找代理人去完成工作。但代理人毕竟只是代理人,能代替本人做的事情终究是有限的。因此,当代理人遇到无法自己解决的事情时就会去找本人解决该问题。
在面向对象编程中,“本人”和“代理人”都是对象。如果“本人”对象太忙了,有些工作无法自己亲自完成,就将其交给“代理人”对象负责。
二 、示例程序
下面我们来看一段使用了 Proxy模式的示例程序。这段示例程序实现了一个“带名字的打印机”。说是打印机,其实只是将文字显示在界面上而已。在Main类中会生成Printerproxy类的实例(即“代理人首先我们会给实例赋予名字Alice并在界面中显示该名字。接着会将实例名字改为Bob,然后显示该名字。在设置和获取名字时,都不会生成真正的Printer类的实例(即本人),而是由PrinterProxy类代理。最后,直到我们调用print方法,开始进入实际打印阶段后,Printerproxy类才会生成Printer类的实例。示例程序的类图请参见图2E ,时序图请参见图21-2o
为了让PrinterProxy类与Printer类具有一致性,我们定义了 Printable接口。示例程序的前提是“生成Printer类的实例”这一处理需要花费很多时间。为了在程序中体现这一点,我们在Printer类的构造函数中调用了 heavyJob方法,让它干一些“重活”(虽说是重活,也不过是让程序睡眠5秒钟)
名字 | 说明 |
---|---|
Printer | 表示带名字的打印机的类(本人) |
Printable | Printer和Printable的共同接口 |
Printerproxy | 表示带名字的打印机类(代理人) |
Main | 测试程序行为的类 |
类和接口的一览表
示例程序类图:
示例程序的时序图:
Pronter类
- Printer类是表示“本人”的类。
- 在之前的学习中我们也了解到了,在它的构造函数中,我们让它做一些所谓的“重活“(heavyJob)。
- setPrinterName方法用于设置打印机的名字;getPrinterName用于获取打印机的名字。
- print方法则用于显示带一串打印机名字的文字。
- heavyJob是一个干5秒钟“重活”的方法,它每秒( 1000毫秒)以点号(.)显示一次干活的进度。
- Proxy模式的核心是Printerproxy类。Printer类自身并不难理解。
代码:
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