设计模式(4)–代理模式

Posted by Tango on September 18, 2015

代理模式为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。或者被代理对象的创建需要消耗很多资源,代理可以在客户端作为一个占位符,等到客户端实际使用的时候才创建被代理对象,而不是一次性创建被代理对象。例如一个相册中有很对相片,创建相片对象是需要消耗很大的资源的,我们可以在创建相册的时候使用相应的代理来创建相片,等到浏览相片的时候才创建相片的对象。

模式适用性

  •  远程代理(Remote  Proxy)为一个位于不同的地址空间的对象提供一个本地的代理对象。
  • 虚拟代理(Virtual Proxy)根据需要创建开销很大的对象。
  • 保护代理(Protection Proxy)控制对原始对象的访问。
  • 智能指引(Smart Reference)取代了简单的指针,对引用次数做统计,当引用为0时释放对象。
  • Copy-on-Write代理:它是虚拟代理的一种,把复制(克隆)操作延迟到只有在客户端真正需要时才执行。一般来说,对象的深克隆是一个开销较大的操作,Copy-on-Write代理可以让这个操作延迟,只有对象被用到的时候才被克隆。

模式结构

在代理模式中有三个关键角色:

  • 抽象角色:通过接口或抽象类声明真实角色实现的业务方法。
  • 代理角色:实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • 真实角色:实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

实现

就拿上面中的图片加载作为例子实现一个代理模式应用场景。

#include <iostream>
using namespace std;
class RealImage {
 int m_id;
 public:
 RealImage(int i) {
   m_id = i;
    cout << "   $$ ctor: " << m_id << '\n';
 }
 ~RealImage() {
   cout << "   dtor: " << m_id << '\n';
 }
 void draw() {
   cout << "   drawing image " << m_id << '\n';
 }
};
// 1. Design an "extra level of indirection" wrapper class
class Image
{
// 2. The wrapper class holds a pointer to the real class
 RealImage *m_the_real_thing;
 int m_id;
 static int s_next;
 public:
 Image() {
   m_id = s_next++;
    // 3. Initialized to null
   m_the_real_thing = 0;
 }
 ~Image() {
   delete m_the_real_thing;
 }
 void draw() {
   // 4. When a request comes in, the real object is
    //    created "on first use"
   if (!m_the_real_thing)
   m_the_real_thing = new RealImage(m_id);
   // 5. The request is always delegated
   m_the_real_thing->draw();
 }
};
 int Image::s_next = 1;
 int main() {
   Image images[5];
    for (int i; true;) {
   cout << "Exit[0], Image[1-5]: ";
    cin >> i;
   if (i == 0)
   break;
   images[i - 1].draw();
 }
 system("Pause");
};