設計模式之代理(Proxy)----對象結構型模式

                            設計模式之代理(Proxy)----對象結構型模式

1.意圖
爲其他對象提供一種代理以控制對這個對象的訪問。

2.別名 Surrogate

3.適用性

在需要用比較通用和複雜的對象指針代替簡單的指針的時候,使用Proxyy 模式。下面是一 些可以使用Proxy模式常見情況:

1) 遠程代理(Remote Proxy )爲一個對象在不同的地址空間提供局部代表。 NEXTSTEP[Add94] 使用N X P r o x y 類實現了這一目的。

2 )虛代理(Virtual Proxy )根據需要創建開銷很大的對象。在動機一節描述的ImageProxy就是這樣一種代理的例子。
3) 保護代理(Protection Proxy )控制對原始對象的訪問。保護代理用於對象應該有不同 的訪問權限的時候。
4 )智能指引(Smart Reference )取代了簡單的指針,它在訪問對象時執行一些附加操作。 它的典型用途包括:

*對指向實際對象的引用計數,這樣當該對象沒有引用時,
*當第一次引用一個持久對象時,將它裝入內存。
*在訪問一個實際對象前,檢查是否已經鎖定了它,以確保其他對象不能改變它。

4.結構





5.參與者

*Proxy
---保存一個引用使得代理可以訪問實體。若RealSubject和Subject的接口相同,Proxy會引用Subject。
---提供一個與Subject的接口相同的接口,這樣代理就可以用來替代實體。
---控制對實體的存取,並可能負責創建和刪除他。
---其他功能依賴於代理的類型。
*Subject
---定義RealSubject和Proxy的共用接口,這樣就在任何使用RealSubject的地方都可以使用Proxy.
*RealSubject
---定義Proxy所代表的實體。

6.協作

代理根據其種類,在適當的時候向RealSubject轉發請求。

7.代碼示例:




#ifdef Implementation
class Image {
public:
virtual void Draw(const Point&);
};


class Image;
extern Image* LoadAnImageFile(const char*);
// external function

class ImagePtr {
public:
ImagePtr(const char* imageFile);
virtual ~ImagePtr();


virtual Image* operator->();
virtual Image& operator*();
private:
Image* LoadImage();
private:
Image* _image;
const char* _imageFile;
};

ImagePtr::ImagePtr (const char* theImageFile) {
_imageFile = theImageFile;
_image = 0;
}

Image* ImagePtr::LoadImage () {
if (_image == 0) {
_image = LoadAnImageFile(_imageFile);
}
return _image;
}

Image* ImagePtr::operator-> () {
return LoadImage();
}

Image& ImagePtr::operator* () {
return *LoadImage();
}

void dummy () {

ImagePtr image = ImagePtr("anImageFileName");
image->Draw(Point(50, 100));
// (image.operator->())->Draw(Point(50, 100))

}

#endif

#ifdef SampleCode
#include "iostream.h"
#include "strings.h"

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"));

}

#endif


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章