享元模式(Flyweight),运用共享技术有效的支持大量细粒度的对象。

  • 如果一个应用使用了大量的对象,而大量的这些对象造成了很大的存储开销时就应该考虑使用。
  • 当对象的大多数状态可以外部状态,如果删除对象的外部状态,那么可以用相对较少的共享内存对象取代很多组对象,此时可以考虑使用享元模式。

  • piece.h
  1. #include <string>
  2. enum Color
  3. {
  4. white,
  5. black
  6. };
  7. class Piece
  8. {
  9. public:
  10. Piece(Color color);
  11. void setPoint(int x, int y);
  12. Color GetColor() const;
  13. public:
  14. int m_X;
  15. int m_Y;
  16. private:
  17. Color m_Color;
  18. };
  • piece.cpp
  1. #include "piece.h"
  2. Piece::Piece(Color color)
  3. :m_Color(color)
  4. {
  5. }
  6. void Piece::setPoint(int x, int y)
  7. {
  8. m_X = x;
  9. m_Y = y;
  10. }
  11. Color Piece::GetColor() const
  12. {
  13. return m_Color;
  14. }
  • checkerboard.h
  1. #include <string>
  2. #include "piece.h"
  3. class CheckerBoard
  4. {
  5. public:
  6. CheckerBoard();
  7. void Draw();
  8. void refresh();
  9. void GetPiece(const Piece& piece);
  10. private:
  11. std::string m_Checker;
  12. };
  • checkerboard.cpp
  1. #include <iostream>
  2. #include <string.h>
  3. #include "checkerboard.h"
  4. CheckerBoard::CheckerBoard()
  5. {
  6. for(int m = 0; m < 20; ++m)
  7. {
  8. for(int n = 0; n < 20; ++n)
  9. m_Checker.append("o");
  10. m_Checker.append("\n");
  11. }
  12. }
  13. void CheckerBoard::Draw()
  14. {
  15. std::cout << m_Checker;
  16. }
  17. void CheckerBoard::refresh()
  18. {
  19. system("cls");
  20. std::cout << m_Checker;
  21. }
  22. void CheckerBoard::GetPiece(const Piece& piece)
  23. {
  24. int pos;
  25. pos = (piece.m_Y * 21) + piece.m_X;
  26. if(piece.GetColor() == Color::white)
  27. m_Checker.replace(pos, 1, "-");
  28. else if(piece.GetColor() == Color::black)
  29. m_Checker.replace(pos, 1, "+");
  30. }
  • piecefactory.h
  1. #include <map>
  2. #include "piece.h"
  3. class PieceFactory
  4. {
  5. public:
  6. PieceFactory();
  7. Piece *find(Color color);
  8. private:
  9. std::map<Color, Piece*> m_PiecesMap;
  10. };
  • piecefactory.cpp
  1. #include <memory>
  2. #include "piecefactory.h"
  3. PieceFactory::PieceFactory()
  4. {
  5. }
  6. Piece *PieceFactory::find(Color color)
  7. {
  8. auto piece = m_PiecesMap.find(color);
  9. if(piece != m_PiecesMap.end()){
  10. return piece->second;
  11. }
  12. else
  13. {
  14. Piece* p = new Piece(color);
  15. m_PiecesMap[color] = p;
  16. return p;
  17. }
  18. }
  • main.cpp
  1. /************************************
  2. * @brief : 享元模式
  3. * @author : wzx
  4. * @date : 2020-07-16
  5. * @project : FlyWeight
  6. *************************************/
  7. #include <iostream>
  8. #include <random>
  9. #include <time.h>
  10. #include <thread>
  11. #include <unistd.h>
  12. #include "checkerboard.h"
  13. #include "piecefactory.h"
  14. #include "piece.h"
  15. using namespace std;
  16. void GeneratePoint(Piece* p)
  17. {//随机数生成有点问题
  18. std::mt19937 rnd(time(0));
  19. p->m_X = rnd()%20;
  20. p->m_Y = rnd()%20;
  21. }
  22. int main()
  23. {
  24. CheckerBoard board;
  25. board.Draw();
  26. PieceFactory factory;
  27. for(int n = 0; n < 20; ++n)
  28. {
  29. Piece* p1 = factory.find(Color::black);
  30. GeneratePoint(p1);
  31. sleep(1);
  32. Piece* p2 = factory.find(Color::white);
  33. GeneratePoint(p2);
  34. board.GetPiece(*p2);
  35. board.GetPiece(*p1);
  36. board.refresh();
  37. }
  38. return 0;
  39. }
  • 运行结果

oooooooooooooooooooo

oooooooooo+ooooooooo

-+oooooooooooooooooo

oooooooooooooooooooo

ooooooo-oooo+oo+oooo

oooooooooooooooooooo

o+oooooooooooooooooo

oooo++oo+ooooooooooo

注:随机数生成算法有点问题,这里忽略最终结果

模式的优点

  • 享元模式可以避免大量非常相似类的开销。在程序设计中,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例除了几个参数外基本都是相同的,有时就能够受大幅度地减少需要实例化的类的数量。如果能把哪些参数移到类实例的外面,在方法调用的时候将它们传递进来,就可以通过共享大幅度地减少单个实例的数目。

模式的缺点

  • 使用享元模式需要维护一个记录了系统已有的所有享元的列表,而这本身需要耗费资源。
  • 享元模式使得系统更加的复杂,为了使对象可以共享,需要将一些状态外部化,这是得程序的逻辑复杂化。因此,应当在有足够多的对象实例可供共享时才值得使用享元模式。

版权声明:本文为wzxNote原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wzxNote/p/13330211.html