十二、Proxy(代理)
情景举例:
为其他对象提供一种代理以控制对这个对象的访问。
四种常见情况:(1)远程代理(2)虚代理(3)保护代理(4)智能指针
代码示例:
/* 这个例子是虚代理的例子。 */ /* 代理类与实际类公共接口 */ class Graphic { public: virtual ~Graphic(); /* */ virtual void Draw(const Point& at) = 0; virtual void HandleMouse(Event& event) = 0; /* */ virtual const Point& GetExtent() = 0; /* */ virtual void Load(istream& from) = 0; virtual void Save(ostream& to) = 0; protected: Graphic(); }; /* 实际类 */ class Image : public Graphic { public: Image(const char* file); // loads image from a file virtual ~Image(); /* */ virtual void Draw(const Point& at); virtual void HandleMouse(Event& event); /* */ virtual const Point& GetExtent(); /* */ virtual void Load(istream& from); virtual void Save(ostream& to); private: // ... }; /* 代理类 */ class ImageProxy : public Graphic { public: ImageProxy(const char* imageFile); virtual ~ImageProxy(); /* */ virtual void Draw(const Point& at); virtual void HandleMouse(Event& event); /* */ virtual const Point& GetExtent(); /* */ virtual void Load(istream& from); virtual void Save(ostream& to); protected: Image* GetImage(); private: Image* _image; Point _extent; char* _fileName; }; /* 构造函数只保存了文件名,并不实际打开文件。 */ ImageProxy::ImageProxy (const char* fileName) { _fileName = strdup(fileName); _extent = Point::Zero; // don't know extent yet _image = 0; } /* 只有当实际需要使用文件时才真正生成对象(延迟处理) */ Image* ImageProxy::GetImage() { if (_image == 0) { _image = new Image(_fileName); } return _image; } const Point& ImageProxy::GetExtent () { if (_extent == Point::Zero) { _extent = GetImage()->GetExtent(); } return _extent; } /* */ void ImageProxy::Draw (const Point& at) { GetImage()->Draw(at); } /* */ void ImageProxy::HandleMouse (Event& event) { GetImage()->HandleMouse(event); } /* */ void ImageProxy::Save (ostream& to) { to << _extent << _fileName; } /* */ void ImageProxy::Load (istream& from) { from >> _extent >> _fileName; } /* */ class TextDocument { public: TextDocument(); void Insert(Graphic*); // ... }; /* 主程序中演示了代理的用法。 */ void dummy () { /* */ TextDocument* text = new TextDocument; // ... text->Insert(new ImageProxy("anImageFileName")); /* */ }个人理解:
代理模式是一种有各种变形的、应用非常广泛的模式。模式的关键是代理类与实际类拥有共同的父类(例中的Graphic类),而在代理类中保存着实际类的引用,代理类则可以在使用实际类之前添加自己的操作。