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

举个围棋的例子,围棋的棋盘共有361格,即可放361个棋子。现在要实现一个围棋程序,该怎么办呢?首先要考虑的是棋子棋盘的实现,可以定义一个棋子的类,成员变量包括棋子的颜色、形状、位置等信息,另外再定义一个棋盘的类,成员变量中有个容器,用于存放棋子的对象。下面给出代码表示:

棋子的定义,当然棋子的属性除了颜色和位置,还有其他的,这里略去。这两个属性足以说明问题。

[cpp] view plaincopy print?
  1. //棋子颜色
  2. enum PieceColor {BLACK, WHITE};
  3. //棋子位置
  4. struct PiecePos
  5. {
  6. int x;
  7. int y;
  8. PiecePos(int a, int b): x(a), y(b) {}
  9. };
  10. //棋子定义
  11. class Piece
  12. {
  13. protected:
  14. PieceColor m_color; //颜色
  15. PiecePos m_pos;     //位置
  16. public:
  17. Piece(PieceColor color, PiecePos pos): m_color(color), m_pos(pos) {}
  18. ~Piece() {}
  19. virtual void Draw() {}
  20. };
  21. class BlackPiece: public Piece
  22. {
  23. public:
  24. BlackPiece(PieceColor color, PiecePos pos): Piece(color, pos) {}
  25. ~BlackPiece() {}
  26. void Draw() { cout<<"绘制一颗黑棋"<<endl;}
  27. };
  28. class WhitePiece: public Piece
  29. {
  30. public:
  31. WhitePiece(PieceColor color, PiecePos pos): Piece(color, pos) {}
  32. ~WhitePiece() {}
  33. void Draw() { cout<<"绘制一颗白棋"<<endl;}
  34. };

棋盘的定义:

[cpp] view plaincopy print?
  1. class PieceBoard
  2. {
  3. private:
  4. vector<Piece*> m_vecPiece; //棋盘上已有的棋子
  5. string m_blackName; //黑方名称
  6. string m_whiteName; //白方名称
  7. public:
  8. PieceBoard(string black, string white): m_blackName(black), m_whiteName(white){}
  9. ~PieceBoard() { Clear(); }
  10. void SetPiece(PieceColor color, PiecePos pos) //一步棋,在棋盘上放一颗棋子
  11. {
  12. Piece * piece = NULL;
  13. if(color == BLACK) //黑方下的
  14. {
  15. piece = new BlackPiece(color, pos); //获取一颗黑棋
  16. cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
  17. piece->Draw(); //在棋盘上绘制出棋子
  18. }
  19. else
  20. {
  21. piece = new WhitePiece(color, pos);
  22. cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
  23. piece->Draw();
  24. }
  25. m_vecPiece.push_back(piece);  //加入容器中
  26. }
  27. void Clear() //释放内存
  28. {
  29. int size = m_vecPiece.size();
  30. for(int i = 0; i < size; i++)
  31. delete m_vecPiece[i];
  32. }
  33. };

客户的使用方式如下:

[cpp] view plaincopy print?
  1. int main()
  2. {
  3. PieceBoard pieceBoard("A","B");
  4. pieceBoard.SetPiece(BLACK, PiecePos(4, 4));
  5. pieceBoard.SetPiece(WHITE, PiecePos(4, 16));
  6. pieceBoard.SetPiece(BLACK, PiecePos(16, 4));
  7. pieceBoard.SetPiece(WHITE, PiecePos(16, 16));
  8. }

可以发现,棋盘的容器中存放了已下的棋子,而每个棋子包含棋子的所有属性。一盘棋往往需要含上百颗棋子,采用上面这种实现,占用的空间太大了。如何改进呢?用享元模式。其定义为:运用共享技术有效地支持大量细粒度的对象。

在围棋中,棋子就是大量细粒度的对象。其属性有内在的,比如颜色、形状等,也有外在的,比如在棋盘上的位置。内在的属性是可以共享的,区分在于外在属性。因此,可以这样设计,只需定义两个棋子的对象,一颗黑棋和一颗白棋,这两个对象含棋子的内在属性;棋子的外在属性,即在棋盘上的位置可以提取出来,存放在单独的容器中。相比之前的方案,现在容器中仅仅存放了位置属性,而原来则是棋子对象。显然,现在的方案大大减少了对于空间的需求。

关注PieceBoard 的容器,之前是vector<Piece*> m_vecPiece,现在是vector<PiecePos> m_vecPos。这里是关键。

棋子的新定义,只包含内在属性:

[cpp] view plaincopy print?
  1. //棋子颜色
  2. enum PieceColor {BLACK, WHITE};
  3. //棋子位置
  4. struct PiecePos
  5. {
  6. int x;
  7. int y;
  8. PiecePos(int a, int b): x(a), y(b) {}
  9. };
  10. //棋子定义
  11. class Piece
  12. {
  13. protected:
  14. PieceColor m_color; //颜色
  15. public:
  16. Piece(PieceColor color): m_color(color) {}
  17. ~Piece() {}
  18. virtual void Draw() {}
  19. };
  20. class BlackPiece: public Piece
  21. {
  22. public:
  23. BlackPiece(PieceColor color): Piece(color) {}
  24. ~BlackPiece() {}
  25. void Draw() { cout<<"绘制一颗黑棋\n"; }
  26. };
  27. class WhitePiece: public Piece
  28. {
  29. public:
  30. WhitePiece(PieceColor color): Piece(color) {}
  31. ~WhitePiece() {}
  32. void Draw() { cout<<"绘制一颗白棋\n";}
  33. };

相应棋盘的定义为:

[cpp] view plaincopy print?
  1. class PieceBoard
  2. {
  3. private:
  4. vector<PiecePos> m_vecPos; //存放棋子的位置
  5. Piece *m_blackPiece;       //黑棋棋子
  6. Piece *m_whitePiece;       //白棋棋子
  7. string m_blackName;
  8. string m_whiteName;
  9. public:
  10. PieceBoard(string black, string white): m_blackName(black), m_whiteName(white)
  11. {
  12. m_blackPiece = NULL;
  13. m_whitePiece = NULL;
  14. }
  15. ~PieceBoard() { delete m_blackPiece; delete m_whitePiece;}
  16. void SetPiece(PieceColor color, PiecePos pos)
  17. {
  18. if(color == BLACK)
  19. {
  20. if(m_blackPiece == NULL)  //只有一颗黑棋
  21. m_blackPiece = new BlackPiece(color);
  22. cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
  23. m_blackPiece->Draw();
  24. }
  25. else
  26. {
  27. if(m_whitePiece == NULL)
  28. m_whitePiece = new WhitePiece(color);
  29. cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
  30. m_whitePiece->Draw();
  31. }
  32. m_vecPos.push_back(pos);
  33. }
  34. };

客户的使用方式一样,这里不重复给出,现在给出享元模式的UML图,以围棋为例。棋盘中含两个共享的对象,黑棋子和白棋子,所有棋子的外在属性都存放在单独的容器中。

设计模式C++实现(9)——享元模式相关推荐

  1. 设计模式(十)享元模式Flyweight(结构型)

    设计模式(十)享元模式Flyweight(结构型) 说明: 相对于其它模式,Flyweight模式在PHP实现似乎没有太大的意义,因为PHP的生命周期就在一个请求,请求执行完了,php占用的资源都被释 ...

  2. 北风设计模式课程---13、享元模式

    北风设计模式课程---13.享元模式 一.总结 一句话总结: 不仅要通过视频学,还要看别的博客里面的介绍,搜讲解,搜作用,搜实例 1.享元模式的核心是什么? 对象插入到一个池子里面去,如果池子里面没有 ...

  3. 设计模式之单例模式与享元模式

    设计模式之单例模式与享元模式 摘要 1. 单例模式 2. 享元模式 摘要   单例模式(Single ton)与享元模式(Flyweight)归为对象性能模式. 1. 单例模式   顾名思义,单例就是 ...

  4. 设计模式学习笔记--Flyweight享元模式

    Flyweight模式也叫享元模式,是由GoF提出的23种设计模式中的一种.Flyweight模式是构造型模式之一,它通过与其他类似对象共享数据来减小内存占用,所以叫享元.   此模式解决的是由于大量 ...

  5. 大战设计模式【19】—— 享元模式

    享元模式(Flyweight) 设计模式使用的例子https://github.com/LinkinStars/DesignPatternsAllExample 一.定义 运用共享技术有效地支持大量细 ...

  6. 设计模式(结构型)之享元模式(Flyweight Pattern)

    PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...

  7. [设计模式] 结构型:享元模式(Flyweight Pattern)

    文章目录 什么是享元模式 设计与实现 Integer应用享元模式 什么是享元模式 "享"的意思是"共享","元"的意思是"对象&q ...

  8. [转载] C#面向对象设计模式纵横谈——12. Flyweight享元模式

    主讲:李建忠 来源:http://www.microsoft.com/china/msdn/events/webcasts/shared/webcast/consyscourse/CsharpOOD. ...

  9. 设计模式——享元模式

    定义 使用共享对象可有效地支持大量细粒度的对象 在享元模式中可以共享的相同内容称为 内部状态(Intrinsic State),而那些需要外部环境来设置的不能共享的内容称为 外部状态(Extrinsi ...

  10. JAVA设计模式--享元模式

    目录 一.什么是享元模式 二.享元模式在Java中的典型应用 三.享元模式的结构 单纯享元模式 复合享元模式 四.享元模式应用举例 五.享元模式的适用性 六.享元模式的特点 七.总结 一.什么是享元模 ...

最新文章

  1. 全面解读WEB 2.0
  2. 邻接表存储图的广度优先遍历
  3. 管好统计信息,开启SQL优化之门
  4. Emmet插件使用方法总结
  5. go--基本数据类型
  6. OpenCV cv :: Mat的串行输出功能的实例(附完整代码)
  7. 关于mysql数据库的外键插入报错:Cannot add or update a child row: a foreign key constraint fails,完整性问题
  8. html 鼠标图标做成动画效果,怎么实现鼠标经过图标动画效果
  9. 华为手机老是显示不到服务器,老显示连接不到服务器
  10. 提交留言HTML模板代码
  11. 阿里巴巴 html圆代码,阿里巴巴国际站HTML代码全透视
  12. mysql端口establish_establish_connection使用方法
  13. 数学工具-desmos 图形曲线
  14. 微信支付(java版本)
  15. 不用跑项目,组件效果所见即所得,绝了~
  16. FPGA 数字信号处理之 FSK 调制、解调的实现与仿真基于 verilog + ise + modelsim + matlab (保姆级)
  17. 小区安装人脸识别系统,先回答五大安全问题
  18. WIN10极限清理 C盘空间
  19. Linux 环境部署|Anaconda及Tensorflow
  20. 网络课设之规划大学校园网

热门文章

  1. AI之Robot:带你玩转机器人DIY机器人——让你成为机器人的真正主人
  2. TF:利用是Softmax回归+GD算法实现MNIST手写数字图片识别(10000张图片测试得到的准确率为92%)
  3. 成功解决 _mssql.c(568): fatal error C1083: 无法打开包括文件: “sqlfront.h”: No such file or directory
  4. 8.3 TensorFlow BP神经网络构建与超参数的选取
  5. Python运行异常 Original error was: DLL load failed:
  6. OpenJudge 1.7 09:密码翻译 题解
  7. Gym 101964 2018-2019 ACM-ICPC Southeastern European Regional Programming Contest (SEERC 2018)
  8. qt5 + vs2015自定义控件错误:undefend interface
  9. Inside ASP.NET 2.0 – Controls Model(转载)
  10. 电脑蓝屏原因分析利器