Swing


天行健 君子以自强不息

posts - 69, comments - 215, trackbacks - 0, articles - 16
   :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

设计模式:结构模式之Proxy(代理)

Posted on 2007-06-04 10:57 zht 阅读(451) 评论(0)  编辑  收藏 所属分类: 设计模式

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
 }
}