Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,Proxy是代理的意思,我们也许有代理服务器等概念,代理概念可以解释为:在出发点到目的地之间有一道中间层,意为代理.
设计模式中定义: 为其他对象提供一种代理以控制对这个对象的访问.要用再建立
程序举例1:权限访问
public class ForumProxy implements Forum {
private ForumPermissions permissions; private Forum forum; this.authorization = authorization;
public ForumProxy(Forum forum, Authorization authorization, ForumPermissions permissions) { this.forum = forum; this.authorization = authorization; this.permissions = permissions; }
.....
public void setName(String name) throws UnauthorizedException, ForumAlreadyExistsException { //只有是系统或论坛管理者才可以修改名称 if (permissions.isSystemOrForumAdmin()) { forum.setName(name); } else { throw new UnauthorizedException(); } }
...
}
|
而DbForum才是接口Forum的真正实现,以修改论坛名称为例:
public class DbForum implements Forum, Cacheable { ...
public void setName(String name) throws ForumAlreadyExistsException {
....
this.name = name; //这里真正将新名称保存到数据库中 saveToDb();
.... }
...
}
|
凡是涉及到对论坛名称修改这一事件,其他程序都首先得和ForumProxy打交道,由ForumProxy决定是否有权限做某一样事情,ForumProxy是个名副其实的"网关","安全代理系统".
程序举例2:用到才创建
实际执行打印 为了模仿长时间操作 在构建的时候延迟5S
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("完成。");
}
}
代理类:真正要打印了才去调用生成printer并且参数赋值进行打印操作
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("Proxy." + className)
.newInstance();
real.setPrinterName(name);
} catch (ClassNotFoundException e) {
System.err.println("找不到类 " + className + "。");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
无论怎么调用setPrinterName方法都不会产生real实例 只有真正需要生成本人的时候才会生成
测试方法:
public class Main {
public static void main(String[] args) {
Printable p = new PrinterProxy("Alice", "Printer");
System.out.println("现在的名称是" + p.getPrinterName() + "。");
p.setPrinterName("Bob");
//不会生成Printer
System.out.println("现在的名称是" + p.getPrinterName() + "。");
//不会生成Printer
p.print("Hello, world.");
//生成Printer
}
}