zoukankan      html  css  js  c++  java
  • 设计模式--享元模式Flyweight(结构型)

    一、享元模式

    在一个系统中如果有多个相同的对象,这些对象有部分状态是可以共享的,我们运用共享技术就能有效地支持大量细粒度的对象。

    二、例子

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

    (1)未采用享元模式的实现

    //棋子颜色
    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; //颜色
        PiecePos m_pos;     //位置
    public:
        Piece(PieceColor color, PiecePos pos): m_color(color), m_pos(pos) {}
        ~Piece() {}
        virtual void Draw() {}
    };
    class BlackPiece: public Piece
    {
    public:
        BlackPiece(PieceColor color, PiecePos pos): Piece(color, pos) {}
        ~BlackPiece() {}
        void Draw() { cout<<"绘制一颗黑棋"<<endl;}
    };
    class WhitePiece: public Piece
    {
    public:
        WhitePiece(PieceColor color, PiecePos pos): Piece(color, pos) {}
        ~WhitePiece() {}
        void Draw() { cout<<"绘制一颗白棋"<<endl;}
    };
    
    class PieceBoard
    {
    private:
        vector<Piece*> m_vecPiece; //棋盘上已有的棋子
        string m_blackName; //黑方名称
        string m_whiteName; //白方名称
    public:
        PieceBoard(string black, string white): m_blackName(black), m_whiteName(white){}
        ~PieceBoard() { Clear(); }
        void SetPiece(PieceColor color, PiecePos pos) //一步棋,在棋盘上放一颗棋子
        {
            Piece * piece = NULL;
            if(color == BLACK) //黑方下的
            {    
                piece = new BlackPiece(color, pos); //获取一颗黑棋
                cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
                piece->Draw(); //在棋盘上绘制出棋子
            }
            else
            {    
                piece = new WhitePiece(color, pos);
                cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
                piece->Draw();
            }
            m_vecPiece.push_back(piece);  //加入容器中
        }
        void Clear() //释放内存
        {
            int size = m_vecPiece.size();
            for(int i = 0; i < size; i++)
                delete m_vecPiece[i];
        }
    };
    
    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));
    }

    (2)采用享元模式

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

    //棋子颜色
    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);
        }
    };

    三、UML图,以围棋为例。棋盘中含两个共享的对象,黑棋子和白棋子,所有棋子的外在属性都存放在单独的容器中。

    参考:

    http://blog.csdn.net/wuzhekai1985/article/details/6670298

  • 相关阅读:
    学习了一下调色理论
    几个同步软件
    慢性咽炎
    flash行情
    C#创建Windows服务
    .net下 foreach 与 for 的效率比较测试
    HTML服务器控件与Web服务器控件的区别
    c#遍历HashTable
    ASP.NET中Server与Request对象的方法
    .net内存回收与Dispose﹐Close﹐Finalize方法
  • 原文地址:https://www.cnblogs.com/justkong/p/6235870.html
Copyright © 2011-2022 走看看