设计模式C++实现(8)——代理模式

[DP]上的定义:为其他对象提供一种代理以控制对这个对象的访问。有四种常用的情况:(1)远程代理,(2)虚代理,(3)保护代理,(4)智能引用。本文主要介绍虚代理和智能引用两种情况。

       考虑一个可以在文档中嵌入图形对象的文档编辑器。有些图形对象的创建开销很大。但是打开文档必须很迅速,因此我们在打开文档时应避免一次性创建所有开销很大的对象。这里就可以运用代理模式,在打开文档时,并不打开图形对象,而是打开图形对象的代理以替代真实的图形。待到真正需要打开图形时,仍由代理负责打开。这是[DP]一书上的给的例子。下面给出代理模式的UML图。

       简单实现如下:

  1. class Image  
  2. {  
  3. public:  
  4.     Image(string name): m_imageName(name) {}  
  5.     virtual ~Image() {}  
  6.     virtual void Show() {}  
  7. protected:  
  8.     string m_imageName;  
  9. };  
  10. class BigImage: public Image  
  11. {  
  12. public:  
  13.     BigImage(string name):Image(name) {}  
  14.     ~BigImage() {}  
  15.     void Show() { cout<<"Show big image : "<<m_imageName<<endl; }  
  16. };  
  17. class BigImageProxy: public Image  
  18. {  
  19. private:  
  20.     BigImage *m_bigImage;  
  21. public:  
  22.     BigImageProxy(string name):Image(name),m_bigImage(0) {}  
  23.     ~BigImageProxy() { delete m_bigImage; }  
  24.     void Show()   
  25.     {  
  26.         if(m_bigImage == NULL)  
  27.             m_bigImage = new BigImage(m_imageName);  
  28.         m_bigImage->Show();  
  29.     }  
  30. };  

         客户调用:

  1. int main()  
  2. {  
  3.     Image *image = new BigImageProxy("proxy.jpg"); //代理  
  4.     image->Show(); //需要时由代理负责打开  
  5.     delete image;  
  6.     return 0;  
  7. }  

         在这个例子属于虚代理的情况,下面给两个智能引用的例子。一个是C++中的auto_ptr,另一个是smart_ptr。自己实现了一下。先给出auto_ptr的代码实现:

  1. template<class T>    
  2. class auto_ptr {    
  3. public:    
  4.     explicit auto_ptr(T *p = 0): pointee(p) {}    
  5.     auto_ptr(auto_ptr<T>& rhs): pointee(rhs.release()) {}    
  6.     ~auto_ptr() { delete pointee; }    
  7.     auto_ptr<T>& operator=(auto_ptr<T>& rhs)    
  8.     {    
  9.         if (this != &rhs) reset(rhs.release());    
  10.         return *this;    
  11.     }    
  12.     T& operator*() const { return *pointee; }    
  13.     T* operator->() const { return pointee; }    
  14.     T* get() const { return pointee; }    
  15.     T* release()    
  16.     {    
  17.         T *oldPointee = pointee;    
  18.         pointee = 0;    
  19.         return oldPointee;    
  20.     }    
  21.     void reset(T *p = 0)    
  22.     {    
  23.         if (pointee != p) {    
  24.                delete pointee;    
  25.                pointee = p;    
  26.             }    
  27.         }    
  28. private:    
  29.     T *pointee;    
  30. };    

        阅读上面的代码,我们可以发现 auto_ptr 类就是一个代理,客户只需操作auto_prt的对象,而不需要与被代理的指针pointee打交道。auto_ptr 的好处在于为动态分配的对象提供异常安全。因为它用一个对象存储需要被自动释放的资源,然后依靠对象的析构函数来释放资源。这样客户就不需要关注资源的释放,由auto_ptr 对象自动完成。实现中的一个关键就是重载了解引用操作符和箭头操作符,从而使得auto_ptr的使用与真实指针类似。

       我们知道C++中没有垃圾回收机制,可以通过智能指针来弥补,下面给出智能指针的一种实现,采用了引用计数的策略。

  1. template <typename T>  
  2. class smart_ptr  
  3. {  
  4. public:  
  5.     smart_ptr(T *p = 0): pointee(p), count(new size_t(1)) { }  //初始的计数值为1  
  6.     smart_ptr(const smart_ptr &rhs): pointee(rhs.pointee), count(rhs.count) { ++*count; } //拷贝构造函数,计数加1  
  7.     ~smart_ptr() { decr_count(); }              //析构,计数减1,减到0时进行垃圾回收,即释放空间  
  8.     smart_ptr& operator= (const smart_ptr& rhs) //重载赋值操作符  
  9.     {  
  10.         //给自身赋值也对,因为如果自身赋值,计数器先减1,再加1,并未发生改变  
  11.         ++*count;  
  12.         decr_count();  
  13.         pointee = rhs.pointee;  
  14.         count = rhs.count;  
  15.         return *this;  
  16.     }    
  17.     //重载箭头操作符和解引用操作符,未提供指针的检查  
  18.     T *operator->() { return pointee; }  
  19.     const T *operator->() const { return pointee; }  
  20.     T &operator*() { return *pointee; }  
  21.     const T &operator*() const { return *pointee; }  
  22.     size_t get_refcount() { return *count; } //获得引用计数器值  
  23. private:   
  24.     T *pointee;       //实际指针,被代理    
  25.     size_t *count;    //引用计数器  
  26.     void decr_count() //计数器减1  
  27.     {  
  28.         if(--*count == 0)   
  29.         {  
  30.             delete pointee;  
  31.             delete count;  
  32.         }  
  33.     }  
  34. };  

         本人享有博客文章的版权,转载请标明出处 http://blog.csdn.net/wuzhekai1985

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值