(learn&think)

不浮躁,不自傲,学习,思考,总结

浅谈设计模式十四: 代理模式(Proxy)

| Comments

1 实例

在酒吧,有不同的酒和喝酒者对象,一开始,喝酒者都能喝酒,没有任何限制。之后,规定年纪小于 16 岁的不应该喝酒。那么如何在不改动众多的酒类的情况下,限制喝酒的年纪呢?

2 代理模式(Proxy)

2.1 目的

为其他的对象提供一个代理来控制访问某个对象。

2.2 实现

这里仅仅是保护代理的一个例子,保护代理控制对原对象的访问。

为酒类添加个代理类,有代理类控制喝酒的年纪,喝酒者如同使用实际酒类一样,使用代理酒类,因为代理酒类和实际酒类拥有共同的基类接口。代码实例在这里

  1. ProxyBearBear 都继承于 Wine;
  2. ProxyBear 维护一个实际 Bear 的实例,由它代理访问实际对象;
  3. ProxyBeardrink 函数中,添加年纪控制。
class ProxyBear : public Wine {
 public:
  explicit ProxyBear(Drinker *drinker);
  virtual ~ProxyBear();
  virtual void drink();
 private:
  Wine *real_bear_;
  Drinker *drinker_;
};

#define kDrinkAge 16
ProxyBear::ProxyBear(Drinker *drinker) : drinker_(drinker) {
  real_bear_ = new Bear();
}

ProxyBear::~ProxyBear() {
  delete real_bear_;
  delete drinker_;
}

void ProxyBear::drink() {
  if (drinker_->age() < kDrinkAge) {
    cout << "Sorry the drinker is too young to drink" << endl;
  } else {
    real_bear_->drink();
  }
}

3 总结

3.1 代理模式(Proxy)结构

3.2 组成

  • 代理类(Proxy)
    1. 保存一个实际主体的引用让代理可以访问它。代理也可以引用主体(Subject)如果实际主体(RealSubject)和主体(Subject)的接口是一样的。
    2. 提供一个与主体(Subjuect)一致的接口,那么代理类就能替代成实际主体。
    3. 控制对实际主体的访问,并且可以负责实际主体的创建或删除。
    4. 其他职责依赖于代理的类型:
      • 远程代理(remote proxies)负责加密一个请求和它的参数,并把它发送给在不同地址空间的实际主体。
      • 虚拟代理(virtual proxies)可以缓存实际主体的附加信息,以便延迟对它的访问。
      • 保护代理(protection proxies)检查调用者是否有访问权限来进行一个请求。
  • 主体(Subject)为实际主体(RealSubject)和代理(Proxy)定义共同的接口,这样一个代理能被用在任何实际主体希望被使用的地方。
  • 实际主体(RealSubject)定义代理表示的实际对象。

3.3 应用场景

代理非常适用,当需要相较于简单指针更通用或更复杂的对一个对象的引用时。下面是一些代理模式适用的常见情况:

  1. 一个远程代理为一个在不同地址空间的对象提供本地的表示。
  2. 一个虚拟代理按需创建一个开销大的对象。
  3. 一个保护代理控制对原对象的访问。保护代理非常实用当对象需要不同的访问权限。
  4. 智能指引(smart reference)用来取代简单的指针指引,并执行附加操作当访问时。

Comments