软件领域中的设计模式为开发人员提供了一种使用专家设计经验的有效途径。设计模式中运用了面向对象编程语言的重要特性:封装、继承、多态,真正领悟设计模式的精髓是可能一个漫长的过程,需要大量实践经验的积累。最近看设计模式的书,对于每个模式,用C++写了个小例子,加深一下理解。主要参考《大话设计模式》和《设计模式:可复用面向对象软件的基础》(DP)两本书。本文介绍代理模式的实现。

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

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

简单实现如下:

[cpp] view plaincopy print?
  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. };

客户调用:

[cpp] view plaincopy print?
  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的代码实现:

[cpp] view plaincopy print?
  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++中没有垃圾回收机制,可以通过智能指针来弥补,下面给出智能指针的一种实现,采用了引用计数的策略。

[cpp] view plaincopy print?
  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. };

设计模式C++实现(8)——代理模式相关推荐

  1. 设计模式(四)--代理模式

    设计模式(四)–代理模式 文章目录 设计模式(四)--代理模式 其他链接 代理模式 1.简介 2.静态代理 角色 代码实现 好处 3.动态代理 代码实现 解析 其他链接 JVM学习笔记(一) JVM学 ...

  2. Java设计模式(10)代理模式(Proxy模式)

    理解并使用设计模式,能够培养我们良好的面向对象编程习惯,同时在实际应用中,可以如鱼得水,享受游刃有余的乐趣. Proxy是比较有用途的一种模式,而且变种较多,应用场合覆盖从小结构到整个系统的大结构,P ...

  3. 【设计模式与体系结构】代理模式

    [设计模式与体系结构]代理模式 文章目录 [设计模式与体系结构]代理模式 一.实例分析 二.代码实现 三.实现结果 一.实例分析 (1) 代理模式设计一个房产中介的模拟程序. 要求:房产中介有介绍和代 ...

  4. 设计模式学习之1—代理模式

    设计模式学习之1-代理模式 0.?先看这里 --- 诗雨的学习说明 1.从生活中初识代理 2.代理模式的类图和角色 3.静态代理和动态代理 4.静态代理 和 动态代理 的 使用模板 4.1 静态代理使 ...

  5. 《拉勾Java高薪课程》阶段一输出 之 通过房屋租赁流程理解设计模式(单例模式,代理模式,工厂模式)--菜鸟小回

    通过房屋租赁流程理解设计模式(单例模式,代理模式,工厂模式) 文章目录 通过房屋租赁流程理解设计模式(单例模式,代理模式,工厂模式) @[toc] 一.单例模式 1. 相关概念 2. 演示思路 3. ...

  6. 设计模式笔记15:代理模式(Proxy Pattern)

    一.代理模式的内容        代理模式为另一个对象提供一个替身或占位符以访问这个对象.         给某一个对象提供一个代理,并由代理对象控制对原对象的引用.代理模式的英文叫做Proxy或Su ...

  7. C#设计模式之十二代理模式(Proxy Pattern)【结构型】

    一.引言 今天我们要讲[结构型]设计模式的第七个模式,也是"结构型"设计模式中的最后一个模式,该模式是[代理模式],英文名称是:Proxy Pattern.还是老套路,先从名字上来 ...

  8. Java设计模式(13)----------代理模式

    原文:https://www.imooc.com/article/24850 默课道可工程师学习地址:https://www.imooc.com/article/24850 介绍 代理模式中,在客户端 ...

  9. 设计模式笔记十三:代理模式

    原文:http://www.runoob.com/design-pattern/ 少许个人理解,如有错误请指出.欢迎一起讨论. 代理模式(Proxy Pattern): 一个类代表另一个类的功能.这种 ...

  10. 【设计模式】第二章 代理模式

    第二章 代理模式 文章目录 第二章 代理模式 一.简介 一.静态代理 二.动态代理 1.JDK 代理 2.CGLib 代理 三.总结 一.简介 你可能会对这个设计模式感到陌生,但是你对 Spring ...

最新文章

  1. linux文本编辑nano
  2. 机器学习中目标函数、损失函数、代价函数之间的区别和联系
  3. MySQL5.6 新特性(全局事务标示符(GTID))
  4. java8中-_java8中的Stream
  5. Hibernate的批量操作
  6. 30美元攻陷Intel SGX enclave,Intel 不打算修复
  7. 华为摄像头搜索软件_华为Mate 40 Pro评测:硬件和软件表现都近乎完美
  8. windows msiexec quiet静默安装及卸载msi软件包
  9. 20172304 2017-2018-2 《程序设计与数据结构》第八周学习总结
  10. Vmware Workstation虚拟机繁忙导致虚拟机系统死机
  11. HTML多选框,全选,多选
  12. 入侵检测领域数据集总结
  13. 【HTML】元素的 alt 和 title 有什么区别?
  14. u深度制作linux启动盘制作工具,u深度u盘启动盘制作工具 v3.1.15.316
  15. linux下的buff/cache内存占用过高-手动清除释放内存
  16. crmeb 多商户app打包教程
  17. 带你轻松写出第一篇优秀论文
  18. asp.net不用服务器控件
  19. opencv HoughLine 理解
  20. 权限提升-网站权限后台漏洞第三方获取

热门文章

  1. DL之InceptionV4/ResNet:InceptionV4/Inception-ResNet算法的简介(论文介绍)、架构详解、案例应用等配图集合之详细攻略
  2. DL之pix2pix(cGAN)之AC:基于pix2pix(cGAN)模型实现对图像实现Auto Color自动上色技术
  3. Dataset之CIFAR-10:CIFAR-10数据集简介、下载、使用方法之详细攻略
  4. OS_CORE.C(总结)
  5. Window上,启动Tomcat服务之后,关闭启动窗口,服务器也随之关闭
  6. iOS开发 tabBarController选中状态
  7. 契约式设计(DbC)感想(二)
  8. joa-framework 工作流高速开发框架(jeecg官方工作流版本号) 公布
  9. 论论资排辈和有能者居之
  10. Stm32 IAP程序编写及用户程序编写