代理模式:为其他对象提供一种代理以控制对这个对象的访问。
有四种常用的情况:
- 远程代理: 为一个对象在不同的地址空间提供局部代表。例如:
使用代理服务器访问远程服务器,能够
1)提高访问速度:因为通常代理服务器都设置一个较大的硬盘缓冲区,当有外界的信息通过时,同时也将其保存到 缓冲区中,当其他用户再访问相同的信息时,则直接由缓冲区中取出信息,传给用户,以提高访问速度。
2)隐藏真实IP
3)突破IP封锁,访问国外站点、访问一些单位或团体内部资源,如某大学内部FTP
- 虚拟代理: 根据需要创建开销很大的对象,如加载图片
- 保护代理: 控制对原始对象的访问,用于对象有不同的访问权限的时候
- 智能指引:取代了简单的指针,在访问对象时执行了一些附加的操作。如C++中的auto_ptr就是使用了代理模式,使我们可以不关注资源的释放。(执行附加的操作可以理解为对原始类作前处理和后处理等)
先访问代理类再访问真正要访问的对象。似乎这样有点多此一举的味道,其实不然。代理类可以在真正的类执行之前,进行预处理。 比富士康生产的手机之前可能会坚持元器件是否合格,不合格就不生产等。在比如你有一个系统实现了登陆功能,在用户登录时, 真正的登录类和代理登录类都实现了Login接口, 不同的是Proxy类的方法中增加了用户是否合法的判断, 只有合法时才去调用真正登录类的login方法. 用户访问的其实是Proxy的login方法.这都是代理模式的优点。而且采用代理模式的话,并且你可以随时更改代理。还有一点你会发现,真正对象与代理他们实现同一个接口。
这个模式和装饰者模式有点类似之处,都是包装,但是请注意他们应用场景不一样:一个是动态的给类添加职责,一个是控制对这个对象的访问。最重要的一点不同是他们的结构不同,具体参加UML类图。
代码:
#include <iostream> #include <string> using namespace std; class Girl { public: Girl(string name) :_name(name){} string getName() const { return _name; } private: string _name; }; class IGiveGift { public: virtual ~IGiveGift() {} public: virtual void giveFlowers() = 0; virtual void giveDolls() = 0; }; class Pursuit : public IGiveGift { public: Pursuit(string name, Girl *g) :_girl(g), _name(name){} public: virtual void giveFlowers() { cout << _girl->getName() << "送你鲜花" << endl; } virtual void giveDolls() { cout << _girl->getName() << "送你玩具" << endl; } string getName() const { return _name; } private: Girl *_girl; string _name; }; class Proxy : public IGiveGift { public: Proxy(string name, Girl *g) { _pursuit = new Pursuit(name, g); } ~Proxy() { delete _pursuit; } virtual void giveFlowers() { cout << _pursuit->getName() << "说: "; _pursuit->giveFlowers(); } virtual void giveDolls() { cout << _pursuit->getName() << "说: "; _pursuit->giveDolls(); } private: Pursuit *_pursuit; }; void test() { Girl g("marry"); Proxy p("peter", &g); p.giveFlowers(); p.giveDolls(); } int main() { test(); cin.get(); return 0; }
效果:
控制访问权限:
虚拟代理:
#include <iostream> #include <string> using namespace std; class Image { public: Image(string name) :_name(name){} virtual ~Image() {} virtual void show() = 0; protected: string _name; }; class BigImage : public Image { public: BigImage(string name) :Image(name){} virtual void show() { cout << "Display big image " << _name << endl; } }; class BigImageProxy : public Image { public: BigImageProxy(string name):Image(name), _bigImage(NULL){} ~BigImageProxy() { if (_bigImage != NULL) { delete _bigImage; _bigImage = NULL; } } virtual void show() { if (_bigImage == NULL) { _bigImage = new BigImage(_name); } _bigImage->show(); } private: BigImage *_bigImage; string _name; }; void test() { Image *image = new BigImageProxy("cat.jpg"); image->show(); delete image; } int main() { test(); cin.get(); return 0; }
智能指针
#include <iostream> #include <string> #include <memory> using namespace std; template<class T> class Auto_ptr { public: explicit Auto_ptr(T *p = 0) :_ptr(p){} Auto_ptr(Auto_ptr<T> &other) :_ptr(other.release()){} Auto_ptr &operator=(Auto_ptr<T>&other) { if (this != &other ) reset(other.release()); return *this; } ~Auto_ptr() { delete _ptr; _ptr = NULL; } T & operator*() const { return *_ptr; } T * operator->() const { return _ptr; } T *get() const { return _ptr; } T * release() { T *tmp = _ptr; _ptr = NULL; return tmp; } void reset(T *p) { if (_ptr != p) { delete _ptr; _ptr = p; } } private: T * _ptr; }; class A { public: A(string name) :_name(name){ cout << "constructor A() " << name << endl; } ~A(){ cout << "destructor ~A() " << _name << endl; } void show() { cout << "I am A" << endl; } private: string _name; }; void test() { Auto_ptr<A> ap(new A("你好")); ap->show(); (*ap).show(); cout << "ap地址 " << ap.get() << endl; cout << "----------------" << endl; Auto_ptr<A> ap2(new A("大家好")); cout << "ap2地址 " << ap2.get() << endl; ap = ap2; cout << "ap地址 " << ap.get() << endl; cout << "ap2地址 " << ap2.get() << endl; ap->show(); cout << "--------------------" << endl; Auto_ptr<A> ap3(ap); cout << "ap地址 " << ap.get() << endl; cout << "ap3地址 " << ap3.get() << endl; } int main() { test(); cin.get(); return 0; }
效果: