十二、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类),而在代理类中保存着实际类的引用,代理类则可以在使用实际类之前添加自己的操作。