設計模式之代理模式(ProxyPattern)
一.代理模式(ProxyPattern)
代理模式是創建一個代理類,來幫助我們處理真實類,一般來說,這種代理類有點像明星的經紀人,如果你想接觸到明星,必須先和他們的經紀人打交道。
注: 接下來爲了方便理解類之間的設計關係,採用StartUML畫類圖,用C++編程
二.編程實例
1.圖片讀取案例
我們再讀取圖片文件時,並不會每一次都把它從磁盤中進行讀取,而是用一個代理類來判斷這個圖片是否已經加載過,如果加載過,那就不用從圖片中再次讀取,可以直接顯示。
類圖設計
:
程序
:
#include <iostream>
#include <string>
using std::string;
using std::cout;
using std::endl;
/*
設計模式之代理模式:
*/
/************************抽象類**************************/
class Image
{
public:
virtual void display() = 0;
};
/************************真實類**************************/
class RealImage:public Image
{
public:
string _filename;
public:
RealImage(string filename)
:_filename(filename)
{
loadFromDisk();
}
void loadFromDisk()
{
cout << _filename << "is loading from disk, it may cost some time" << endl;
}
void display()
{
cout << "display: " << _filename << endl;
}
};
/************************代理類**************************/
class ProxyImage:public Image
{
public:
RealImage* _realImage;
string _filename;
public:
ProxyImage(string filename)
:_filename(filename)
,_realImage(NULL)
{}
void display()
{
if (_realImage == NULL)
_realImage = new RealImage(_filename);
_realImage->display();
}
};
int main()
{
Image *image1 = new ProxyImage("Adult Picture");
image1->display();
cout << "I want to see Adult Picture again" << endl;
image1->display();
return 0;
}
2.String類訪問修飾符[]讀寫操作區分案例
這個案例有一些難度,如果像瞭解完整的String類實現,可以參考我的另一篇文章:String類COW寫時複製技術
在我們重載訪問修飾符[]的時候,我們並不能夠分清楚它究竟是要進行讀操作還是寫操作,因爲寫操作需要重新分配內存而讀操作不需要,所以我們用一個代理類來幫助我們進行判斷。
程序
:
#include <iostream>
#include <string>
using std::cout;
using std::endl;
using std::string;
//沒有用代理模式
#if 0
class String
{
char *_pstr;
public:
String()
: _pstr(new char[100])
{
_pstr[0] = 'a';
}
char &operator[](int idx)
{
cout << "無法分清讀寫操作,直接重新分配內存,很消耗時間" << endl;
_pstr = new char[100];
_pstr[0] = 'a';
return _pstr[idx];
}
void operator=(const char &ch)
{
_pstr[0] = ch;
}
};
#endif
//使用代理模式
#if 1
class String
{
char *_pstr;
public:
//代理類
class CharProxy
{
String &_string;
int _idx;
public:
CharProxy(String &string, int idx)
: _string(string), _idx(idx)
{
}
//讀操作
operator char()
{
return _string._pstr[_idx];
}
//寫操作
void operator=(const char &ch)
{
cout << "重新分配內存" << endl;
_string._pstr[_idx] = ch;
}
};
public:
String()
: _pstr(new char[100])
{
_pstr[0] = 'a';
}
CharProxy operator[](int idx)
{
return CharProxy(*this, idx);
}
char *c_str()
{
return _pstr;
}
};
#endif
int main()
{
String s1;
cout << s1[0] << endl;
s1[0] = 'd';
return 0;
}