一、享元模式

在一个系统中如果有多个相同的对象,这些对象有部分状态是可以共享的,我们运用共享技术就能有效地支持大量细粒度的对象。

二、例子

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

(1)未采用享元模式的实现

  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. };
  35.  
  36. class PieceBoard
  37. {
  38. private:
  39. vector<Piece*> m_vecPiece; //棋盘上已有的棋子
  40. string m_blackName; //黑方名称
  41. string m_whiteName; //白方名称
  42. public:
  43. PieceBoard(string black, string white): m_blackName(black), m_whiteName(white){}
  44. ~PieceBoard() { Clear(); }
  45. void SetPiece(PieceColor color, PiecePos pos) //一步棋,在棋盘上放一颗棋子
  46. {
  47. Piece * piece = NULL;
  48. if(color == BLACK) //黑方下的
  49. {
  50. piece = new BlackPiece(color, pos); //获取一颗黑棋
  51. cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
  52. piece->Draw(); //在棋盘上绘制出棋子
  53. }
  54. else
  55. {
  56. piece = new WhitePiece(color, pos);
  57. cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
  58. piece->Draw();
  59. }
  60. m_vecPiece.push_back(piece); //加入容器中
  61. }
  62. void Clear() //释放内存
  63. {
  64. int size = m_vecPiece.size();
  65. for(int i = ; i < size; i++)
  66. delete m_vecPiece[i];
  67. }
  68. };
  69.  
  70. int main()
  71. {
  72. PieceBoard pieceBoard("A","B");
  73. pieceBoard.SetPiece(BLACK, PiecePos(, ));
  74. pieceBoard.SetPiece(WHITE, PiecePos(, ));
  75. pieceBoard.SetPiece(BLACK, PiecePos(, ));
  76. pieceBoard.SetPiece(WHITE, PiecePos(, ));
  77. }

(2)采用享元模式

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

  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. };
  34.  
  35. class PieceBoard
  36. {
  37. private:
  38. vector<PiecePos> m_vecPos; //存放棋子的位置
  39. Piece *m_blackPiece; //黑棋棋子
  40. Piece *m_whitePiece; //白棋棋子
  41. string m_blackName;
  42. string m_whiteName;
  43. public:
  44. PieceBoard(string black, string white): m_blackName(black), m_whiteName(white)
  45. {
  46. m_blackPiece = NULL;
  47. m_whitePiece = NULL;
  48. }
  49. ~PieceBoard() { delete m_blackPiece; delete m_whitePiece;}
  50. void SetPiece(PieceColor color, PiecePos pos)
  51. {
  52. if(color == BLACK)
  53. {
  54. if(m_blackPiece == NULL) //只有一颗黑棋
  55. m_blackPiece = new BlackPiece(color);
  56. cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
  57. m_blackPiece->Draw();
  58. }
  59. else
  60. {
  61. if(m_whitePiece == NULL)
  62. m_whitePiece = new WhitePiece(color);
  63. cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
  64. m_whitePiece->Draw();
  65. }
  66. m_vecPos.push_back(pos);
  67. }
  68. };

三、UML图,以围棋为例。棋盘中含两个共享的对象,黑棋子和白棋子,所有棋子的外在属性都存放在单独的容器中。

参考:

http://blog.csdn.net/wuzhekai1985/article/details/6670298

设计模式--享元模式Flyweight(结构型)的更多相关文章

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

    享元模式(FlyWeight)  “享”取“共享”之意,“元”取“单元”之意. 意图 运用共享技术,有效的支持大量细粒度的对象. 意图解析 面向对象的程序设计中,一切皆是对象,这也就意味着系统的运行将 ...

  2. 设计模式11: Flyweight 享元模式(结构型模式)

    Flyweight 享元模式(结构型模式) 面向对象的代价 面向对象很好的解决了系统抽象性的问题,同时在大多数情况下也不会损及系统的性能.但是,在某些特殊应用中,由于对象的数量太大,采用面向对象会给系 ...

  3. Java设计模式15:常用设计模式之享元模式(结构型模式)

    1. Java之享元模式(Flyweight Pattern) (1)概述:       享元模式是对象池的一种实现,英文名为"Flyweight",代表轻量级的意思.享元模式用来 ...

  4. 设计模式-享元模式(FlyWeight)

    一.概念 享元模式是对象的结构模式,它以共享的方式高效的支持大量的细粒度对象,减少对象的数量,并达到节约内存的目的. 享元对象能够做到共享的关键,主要是区分了内部状态和外部状态,内部状态是对象是在建立 ...

  5. 大话设计模式--享元模式 Flyweight -- C++实现实例

    1. 享元模式: 运用共享技术有效地支持大量细粒度的对象. 享元模式可以避免大量非常相似类的开销,在程序设计中,有时需要生成大量颗粒度的类实例来表示数据,如果能发现这些实例除了几个参数外基本都是相同的 ...

  6. 面向对象设计模式之Flyweight享元模式(结构型)

    动机:采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行代价——主要指内存需求方面的代价.如何在避免大量细粒度对象问题的同 时,让外部客户程序仍然能够透明地使用面向对象的 ...

  7. 设计模式 笔记 享元模式 Flyweight

    //---------------------------15/04/20---------------------------- //Flyweight 享元模式------对象结构型模式 /* 1 ...

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

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

  9. 深入浅出设计模式——享元模式(Flyweight Pattern)

    模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生 ...

随机推荐

  1. JSONP跨域操作

    JSP <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3. ...

  2. Vue2.0组件间数据传递

    Vue1.0组件间传递 使用$on()监听事件: 使用$emit()在它上面触发事件: 使用$dispatch()派发事件,事件沿着父链冒泡: 使用$broadcast()广播事件,事件向下传导给所有 ...

  3. shell及脚本1——变量

    一.shell shell是操作系统与用户之间的沟通的渠道,可以接收并执行用户的命令,有很多shell程序,目前linux默认使用bash shell程序. bash shell有很多实用功能,例如: ...

  4. 关于PHP扩展开发(收藏)

    一.Linux shell命令: ls –lh    查看文件大小 du –a    查看文件及文件夹大小 -------------------------- nginx ------------- ...

  5. Nginx 1.10.1 编译、配置文档(支持http_v2,TLSv1.2,openssl v1.0.2)

    1.安装常用工具及基础包: [root@localhost /]# yum -y install wget git vim make gcc gcc-c++ openssl-devel [root@l ...

  6. ionic 图标以及启动页图片不能正确加载

    前段时间莫名其妙的发现发布的app不能正常的现实图标和启动页了,加载出来的图标以及图片显示的都是cordova的默认图片以及启动页图片 在网上找了很多教程各种查找都不能解决方法 表现原因为: 项目根目 ...

  7. python中文编码问题

    第一步:在代码中输入以下命令,执行: #在Python中显示中文注释和输出中文a ="中文"print a 返回错误: d:\Python27\python.exe "D ...

  8. foreach

    一 foreach的语法介绍    PHP 4以上的版本包括了 foreach 结构,这只是一种遍历数组简便方法.foreach 仅能用于数组,当试图将其用于其它数据类型或者一个未初始化的变量时会产生 ...

  9. HTML5 Drop API

    转自:http://www.cnblogs.com/fsjohnhuang/p/3961066.html 一.前言    在HTML4的时代,各前端工程师为了实现拖拽功能可说是煞费苦心,初听HTML5 ...

  10. Struts2之开山篇

    ①Struts2是什么? Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图 ...