享元模式(Flyweight Pattern):用于减少创建对象的数量,以减少内存占用和提高性能。尝试重用现有的同类对象,如果未找到匹配的对象,则创建新对象。 如数据库里的数据池。
享元模式:
重复使用的细粒度的对象的构建和释放,直接一次构造重复使用。
使用场景:
如棋盘游戏,黑白棋子的管理
源码Demo:
参考:C++设计模式——享元模式 - Ring_1992 - 博客园 (cnblogs.com)
/********************************************************* 享元模型: 目的是避免大量非常类似的开销。 如果需要大量相似对象表示数据,只有很少的差异,可以经过一些处理, 把很少差异的参数移动到外部,用传参的方式调用,减少实例化的对象数。 实现demo: 参考网上实例,如下五子棋,红黑节点的双方一直操作的对象,需要一直操作,可以用一个对象管理。(一个房间管理两个棋手,重复利用对象) 更加拓展,如棋牌游戏中,如果多个房间,多人下棋, *********************************************************/ #include <iostream> #include <map> #include <vector> using namespace std; //管理坐标 typedef struct pointTag { int x; int y; pointTag(){} pointTag(int a, int b) { x = a; y = b; } bool operator <(const pointTag& other) const { if (x < other.x) { return true; } else if (x == other.x) { return y < other.y; } return false; } }POINT; //管理红黑子 typedef enum PieceColorTag { BLACK, WHITE }PIECECOLOR; //把棋子的颜色和坐标作为一个对象进行构造 class CPiece { public: CPiece(PIECECOLOR color) : m_color(color){} PIECECOLOR GetColor() { return m_color; } void SetPoint(POINT point) { m_point = point; } //拷贝构造 POINT GetPoint() { return m_point; } protected: PIECECOLOR m_color; POINT m_point; }; //管理棋子 class CGomoku : public CPiece { public: CGomoku(PIECECOLOR color) : CPiece(color){} }; //根据黑白棋 定义一个对象 重复使用 ==》根据入参,可以决定不同的选手 class CPieceFactory { public: CPiece *GetPiece(PIECECOLOR color) { CPiece *pPiece = NULL; if (m_vecPiece.empty()) { pPiece = new CGomoku(color); m_vecPiece.push_back(pPiece); } else { for (vector<CPiece *>::iterator it = m_vecPiece.begin(); it != m_vecPiece.end(); ++it) { if ((*it)->GetColor() == color) { pPiece = *it; break; } } if (pPiece == NULL) { pPiece = new CGomoku(color); m_vecPiece.push_back(pPiece); } } return pPiece; } ~CPieceFactory() { for (vector<CPiece *>::iterator it = m_vecPiece.begin(); it != m_vecPiece.end(); ++it) { if (*it != NULL) { delete *it; *it = NULL; } } } private: vector<CPiece *> m_vecPiece; }; //棋盘管理 class CChessboard { public: //落子 节点坐标对应 共享的一个节点对象 void Draw(CPiece *piece) { if (piece->GetColor()) { cout<<"Draw a White"<<" at ("<<piece->GetPoint().x<<","<<piece->GetPoint().y<<")"<<endl; } else { cout<<"Draw a Black"<<" at ("<<piece->GetPoint().x<<","<<piece->GetPoint().y<<")"<<endl; } m_mapPieces.insert(pair<POINT, CPiece *>(piece->GetPoint(), piece)); } //显示棋盘上所有的节点 void ShowAllPieces() { for (map<POINT, CPiece *>::iterator it = m_mapPieces.begin(); it != m_mapPieces.end(); ++it) { if (it->second->GetColor()) { cout<<"("<<it->first.x<<","<<it->first.y<<") has a White chese."<<endl; } else { cout<<"("<<it->first.x<<","<<it->first.y<<") has a Black chese."<<endl; } } } private: map<POINT, CPiece *> m_mapPieces; }; int main() { //创建一个棋盘管理房间对象 调用方法根据传参选择对手,重复利用两个对象 CPieceFactory *pPieceFactory = new CPieceFactory(); //创建一个棋盘对象 CChessboard *pCheseboard = new CChessboard(); //先手第一个选手 选择白棋 定义坐标并落子 CPiece *pPiece = pPieceFactory->GetPiece(WHITE); //选定对象 pPiece->SetPoint(POINT(2, 3)); pCheseboard->Draw(pPiece); //第二个选手 根据颜色找到自己的棋子进行落子 pPiece = pPieceFactory->GetPiece(BLACK); pPiece->SetPoint(POINT(4, 5)); pCheseboard->Draw(pPiece); //第一个选手落子 pPiece = pPieceFactory->GetPiece(WHITE); pPiece->SetPoint(POINT(2, 4)); pCheseboard->Draw(pPiece); //第二个选手落子 pPiece = pPieceFactory->GetPiece(BLACK); pPiece->SetPoint(POINT(3, 5)); pCheseboard->Draw(pPiece); //展示棋盘上所有的落子 cout<<"Show all cheses"<<endl; pCheseboard->ShowAllPieces(); //删除棋盘 if (pCheseboard != NULL) { delete pCheseboard; pCheseboard = NULL; } //删除房间 if (pPieceFactory != NULL) { delete pPieceFactory; pPieceFactory = NULL; } return 0; }