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

享元模式(c++實現)

享元模式

目錄

模式定義

享元模式(Flyweight),運用共享技術有效的支援大量細粒度的物件。

模式動機

  • 如果一個應用使用了大量的物件,而大量的這些物件造成了很大的儲存開銷時就應該考慮使用。
  • 當物件的大多數狀態可以外部狀態,如果刪除物件的外部狀態,那麼可以用相對較少的共享記憶體物件取代很多組物件,此時可以考慮使用享元模式。

UML類圖

原始碼實現

  • piece.h
#include <string>
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
#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
#include <string>
#include "piece.h"
class CheckerBoard
{
public:
CheckerBoard();
void Draw();
void refresh();
void GetPiece(const Piece& piece); private:
std::string m_Checker;
};
  • checkerboard.cpp
#include <iostream>
#include <string.h>
#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
#include <map>
#include "piece.h"
class PieceFactory
{
public:
PieceFactory();
Piece *find(Color color);
private:
std::map<Color, Piece*> m_PiecesMap;
};
  • piecefactory.cpp
#include <memory>
#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
/************************************
* @brief : 享元模式
* @author : wzx
* @date : 2020-07-16
* @project : FlyWeight
*************************************/
#include <iostream>
#include <random>
#include <time.h>
#include <thread>
#include <unistd.h>
#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

注:隨機數生成演演算法有點問題,這裡忽略最終結果

優點

模式的優點

  • 享元模式可以避免大量非常相似類的開銷。在程式設計中,有時需要生成大量細粒度的類例項來表示資料。如果能發現這些例項除了幾個引數外基本都是相同的,有時就能夠受大幅度地減少需要例項化的類的數量。如果能把哪些引數移到類例項的外面,在方法呼叫的時候將它們傳遞進來,就可以通過共享大幅度地減少單個例項的數目。

缺點

模式的缺點

  • 使用享元模式需要維護一個記錄了系統已有的所有享元的列表,而這本身需要耗費資源。
  • 享元模式使得系統更加的複雜,為了使物件可以共享,需要將一些狀態外部化,這是得程式的邏輯複雜化。因此,應當在有足夠多的物件例項可供共享時才值得使用享元模式。