动机
在软件系统采用纯粹对象方案的问题在于大量细粒度的对象会很快充斥在系统中,从而带来很高的运行时代价,主要指内存需求方面的代价。
要点
享元模式要求被共享的对象必须是细粒度对象。如输入英文段落,26个字母可能随时被客户重复使用。尽管每个字母可能出现的位置不一样,但在物理上它们共享同一个对象(同一个实例)。利用享元模式,可以创建一个存储26个字母对象的享元池,需要时从享元池中取出。
享元对象能够做到共享的关键在于区分了内部状态和外部状态:
内部状态:
存储在享元对象内部,不会随着环境的改变而改变的,内部状态可以共享。比如围棋中棋子的形状、大小;比如字体;
外部状态:
随环境变化而变化、不可以共享的状态,如棋子的位置、颜色,如每个字母的位置。外部状态一般由客户端保存,在使用时再传入到享元对象内部。不同的外部状态之间是相互独立的,棋子A和棋子B的位置可以不同,并且不会相互影响。
结构
实例
enum PieceColor{
BLACK,
WHITE
}
class Pose{
public:
Pose(int _X, int _y)
:x(_x), y(_y){}
int x;
int y;
}
class Piece{
public:
Piece(){}
virtual void Draw() {}
~Piece(){}
}
class BlackPiece : public Piece{
public:
BlackPiece() {}
~BlackPiece() {}
void Draw(){
//......
}
}
class WhihtePiece : public Piece{
public:
WhihtePiece() {}
~WhihtePiece() {}
void Draw(){
//......
}
}
//用单例模式,确保只用一个工厂
class PieceFactory{
public:
static PieceFactory& GetInstance(){
static PieceFactory instance;
return instance;
}
const Piece* GetPiece(const PieceColor& color){
if(color==BLACK){
return &m_blackpiece;
}
else{
return &m_whitepiece;
}
}
~PieceFactory(){}
private:
PieceFactory():m_blackpiece(new BlackPiece),
m_whitepiece(new WhihtePiece) {}
PieceFactory(const PieceFactory& ){}
PieceFactory& operator=(const PieceFactory&){}
WhihtePiece* m_whitepiece;
BlackPiece* m_blackpiece;
}