设计模式 --> (10)享元模式

享元模式

  运用共享技术有效地支持大量细粒度的对象。

  享元对象能做到共享的关键是区分内蕴状态(Internal State)和外蕴状态(External State)。

  内蕴状态是存储在享元对象内部并且不会随环境改变而改变。因此内蕴状态并可以共享。

  外蕴状态是随环境改变而改变的、不可以共享的状态。享元对象的外蕴状态必须由客户端保存,并在享元对象被创建之后,在需要使用的时候再传入到享元对象内部。外蕴状态与内蕴状态是相互独立的。

适用性:

  1.当系统中有大量的细粒度对象实例,而且这些对象实例中有一些属性是重复的情况下,考虑使用。

  2.文本编辑器,输入法之类的常用应用。

优点:

  1.提高了系统的效率,减小了内存的消耗。

  2.减少了重复代码。

  3.减少了系统的复杂度。

缺点:

  1.维护共享对象和查找所需的共享对象需要花费很多时间。

举例

  举个围棋的例子,围棋的棋盘共有361格,即可放361个棋子。现在要实现一个围棋程序,该怎么办呢?首先要考虑的是棋子棋盘的实现,可以定义一个棋子的类,成员变量包括棋子的颜色、形状、位置等信息,另外再定义一个棋盘的类,成员变量中有个容器,用于存放棋子的对象。

  在围棋中,棋子就是大量细粒度的对象。其属性有内在的,比如颜色、形状等,也有外在的,比如 在棋盘上的位置。内在的属性是可以共享的,区分在于外在属性。因此,可以这样设计,只需定义两个棋子的对象,一颗黑棋和一颗白棋,这两个对象含棋子的内在 属性;棋子的外在属性,即在棋盘上的位置可以提取出来,存放在单独的容器中。相比之前的方案,现在容器中仅仅存放了位置属性,而原来则是棋子对象。显然, 现在的方案大大减少了对于空间的需求。

#include <iostream>
#include <vector>
using namespace std;

//棋子颜色  
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<<"绘制一颗黑棋
"; }  
};  

//白棋 
class WhitePiece: public Piece  
{  
public:  
    WhitePiece(PieceColor color): Piece(color) {}  
    ~WhitePiece() {}  
    void Draw() { cout<<"绘制一颗白棋
";}  
};  

//棋盘 
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));  
}   

参考 http://blog.csdn.net/wuzhekai1985

原文地址:https://www.cnblogs.com/jeakeven/p/4966965.html