1. 程式人生 > >享元模式(c++實現)

享元模式(c++實現)

# 享元模式 [TOC] ## 模式定義 **享元模式(Flyweight)**,運用共享技術有效的支援大量細粒度的物件。 ## 模式動機 - 如果一個應用使用了大量的物件,而大量的這些物件造成了很大的儲存開銷時就應該考慮使用。 - 當物件的大多數狀態可以外部狀態,如果刪除物件的外部狀態,那麼可以用相對較少的共享記憶體物件取代很多組物件,此時可以考慮使用享元模式。 ## UML類圖 ![](https://files-cdn.cnblogs.com/files/wzxNote/%E4%BA%AB%E5%85%83%E6%A8%A1%E5%BC%8F.bmp) ## 原始碼實現 - piece.h ```c++ #include enum Color { white, black }; class Piece { public: Piece(Color color); void setPoint(int x, int y); Color GetColor() const; public: int m_X; int m_Y; private: Color m_Color; }; ``` - piece.cpp ```c++ #include "piece.h" Piece::Piece(Color color) :m_Color(color) { } void Piece::setPoint(int x, int y) { m_X = x; m_Y = y; } Color Piece::GetColor() const { return m_Color; } ``` - checkerboard.h ```c++ #include #include "piece.h" class CheckerBoard { public: CheckerBoard(); void Draw(); void refresh(); void GetPiece(const Piece& piece); private: std::string m_Checker; }; ``` - checkerboard.cpp ```c++ #include #include #include "checkerboard.h" CheckerBoard::CheckerBoard() { for(int m = 0; m < 20; ++m) { for(int n = 0; n < 20; ++n) m_Checker.append("o"); m_Checker.append("\n"); } } void CheckerBoard::Draw() { std::cout << m_Checker; } void CheckerBoard::refresh() { system("cls"); std::cout << m_Checker; } void CheckerBoard::GetPiece(const Piece& piece) { int pos; pos = (piece.m_Y * 21) + piece.m_X; if(piece.GetColor() == Color::white) m_Checker.replace(pos, 1, "-"); else if(piece.GetColor() == Color::black) m_Checker.replace(pos, 1, "+"); } ``` - piecefactory.h ```c++ #include #include "piece.h" class PieceFactory { public: PieceFactory(); Piece *find(Color color); private: std::map m_PiecesMap; }; ``` - piecefactory.cpp ```c++ #include #include "piecefactory.h" PieceFactory::PieceFactory() { } Piece *PieceFactory::find(Color color) { auto piece = m_PiecesMap.find(color); if(piece != m_PiecesMap.end()){ return piece->second; } else { Piece* p = new Piece(color); m_PiecesMap[color] = p; return p; } } ``` - main.cpp ```c++ /************************************ * @brief : 享元模式 * @author : wzx * @date : 2020-07-16 * @project : FlyWeight *************************************/ #include #include #include #include #include #include "checkerboard.h" #include "piecefactory.h" #include "piece.h" using namespace std; void GeneratePoint(Piece* p) {//隨機數生成有點問題 std::mt19937 rnd(time(0)); p->m_X = rnd()%20; p->m_Y = rnd()%20; } int main() { CheckerBoard board; board.Draw(); PieceFactory factory; for(int n = 0; n < 20; ++n) { Piece* p1 = factory.find(Color::black); GeneratePoint(p1); sleep(1); Piece* p2 = factory.find(Color::white); GeneratePoint(p2); board.GetPiece(*p2); board.GetPiece(*p1); board.refresh(); } return 0; } ``` - 執行結果 > oooooooooooooooooooo > > oooooooooo+ooooooooo > > -+oooooooooooooooooo > > oooooooooooooooooooo > > ooooooo-oooo+oo+oooo > > oooooooooooooooooooo > > o+oooooooooooooooooo > > oooo++oo+ooooooooooo > > 注:隨機數生成演算法有點問題,這裡忽略最終結果 ## 優點 模式的優點 - 享元模式可以避免大量非常相似類的開銷。在程式設計中,有時需要生成大量細粒度的類例項來表示資料。如果能發現這些例項除了幾個引數外基本都是相同的,有時就能夠受大幅度地減少需要例項化的類的數量。如果能把哪些引數移到類例項的外面,在方法呼叫的時候將它們傳遞進來,就可以通過共享大幅度地減少單個例項的數目。 ## 缺點 模式的缺點 - 使用享元模式需要維護一個記錄了系統已有的所有享元的列表,而這本身需要耗費資源。 - 享元模式使得系統更加的複雜,為了使物件可以共享,需要將一些狀態外部化,這是得程式的邏輯複雜化。因此,應當在有足夠多的物件例項可供共享時才值得使用享元