享元模式在《设计模式:可复用面向对象软件的基础》一书中是这样说的:运用共享技术有效地支持大量细粒度的对象。本质就是对大量细粒度的对象进行共享,不是每个对象都要通过new的方式去创建,而是通过区分对象的内部状态和外部状态来实现共享。以此来达到减少系统的开销,提高程序性能的目的。
在某个类在系统中有大量的实例时,并且可根据这些实例的特征分离出内部状态可外部状态。
以五子棋为例,常规情况如果每下一颗棋就去new一个对象的话。会造成大量重复的系统开销。影响系统性能,显然这种方式是不必要的。那么我们可以使用享元模式来解决此类问题。可以在棋子中抽象出内部状态可外部状态,棋子的属性无非是颜色和位置,颜色非黑即白我们可以作为内部状态,由棋子类的对象来维护,棋子的位置如果也为内部状态,且每颗棋子的位置都是不同的,那每颗棋子仍然是要通过new的方式来构建棋子对象。故棋子的位置要作为外部状态,不在棋子的内部进行维护,而是由上层调用棋子处维护。如此便区分了内部和外部状态,以下代码示例:
//棋子颜色
enum PieceColor {BLACK, WHITE};
//棋子位置
struct PiecePos
{
int x;
int y;
PiecePos(int a, int b): x(a), y(b) {}
};
//棋子定义
class Piece
{
protected:
PieceColor m_color; //颜色
public:
Piece(PieceColor color): m_color(color) {}
~Piece() {}
virtual void Draw() {}
};
class BlackPiece: public Piece
{
public:
BlackPiece(PieceColor color): Piece(color) {}
~BlackPiece() {}
void Draw() { cout<<"绘制一颗黑棋\n"; }
};
class WhitePiece: public Piece
{
public:
WhitePiece(PieceColor color): Piece(color) {}
~WhitePiece() {}
void Draw() { cout<<"绘制一颗白棋\n";}
};
class PieceBoard
{
private:
vector<PiecePos> m_vecPos; //存放棋子的位置
Piece *m_blackPiece; //黑棋棋子
Piece *m_whitePiece; //白棋棋子
string m_blackName;
string m_whiteName;
public:
PieceBoard(string black, string white): m_blackName(black), m_whiteName(white)
{
m_blackPiece = NULL;
m_whitePiece = NULL;
}
~PieceBoard() { delete m_blackPiece; delete m_whitePiece;}
void SetPiece(PieceColor color, PiecePos pos)
{
if(color == BLACK)
{
if(m_blackPiece == NULL) //只有一颗黑棋
m_blackPiece = new BlackPiece(color);
cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
m_blackPiece->Draw();
}
else
{
if(m_whitePiece == NULL)
m_whitePiece = new WhitePiece(color);
cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
m_whitePiece->Draw();
}
m_vecPos.push_back(pos);
}
};
int main()
{
PieceBoard pieceBoard("A","B");
pieceBoard.SetPiece(BLACK, PiecePos(4, 4));
pieceBoard.SetPiece(WHITE, PiecePos(4, 16));
pieceBoard.SetPiece(BLACK, PiecePos(16, 4));
pieceBoard.SetPiece(WHITE, PiecePos(16, 16));
}