结构模式之Proxy(代理)

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值