zoukankan      html  css  js  c++  java
  • 享元模式 FlyWeight

    c++ 享元模式(flyweight)

    例子(大话设计模式上的例子 c++的):

    // FlyWeight.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    
    
    #include <IOSTREAM>
    #include <STRING>
    #include   <map> 
    using namespace std;
    
    ////////////////////////////////////////
    //version 1
    class website1{
    public:
        website1(string name):m_name(name){}
        void show(){
            cout<<this->m_name<<endl;
        }
    
    private:
        string m_name;
    };
    /////////////////////////////////////////
    //version 2
    //实现了共享对象,但是数据都是相同的
    class website2{
    public:
        virtual void show() = 0;
    };
    
    class concretewebsite2:public website2{
    public:
        concretewebsite2(string name):m_name(name){}
        void show(){
            cout<<this->m_name<<endl;
        }
    private:
        string m_name;
    };
    
    class website2factory{
    public:
        concretewebsite2 * getwebsite(string type){
            map<string,concretewebsite2 *>::iterator it ;
            it = m_map.find(type);
            if(it == m_map.end())
                //    m_map.insert(pair<string , concretewebsite *>(type,new concretewebsite(type)));
                    m_map[type] = new concretewebsite2(type);
            return m_map[type];
        }
        int getwebsitecount(){
            return m_map.size();
        }
    private:
        map<string ,concretewebsite2 * > m_map;
    };
    
    //////////////////////////////////////
    //version 3
    class User{
    public:
        User(string name):m_username(name){}
        string getusername() const{
            return m_username;
        }
    private:
        string m_username;
    };
    
    class website3{
    public:
        virtual void show(const User & user) = 0;      //将数据分离开来,但内部处理还是同一对象
    };
    
    class concretewebsite3:public website3{
    public:
        concretewebsite3(string name):m_name(name){}
        void show( const User & user){                     
            cout<<this->m_name<<"   "<<user.getusername()<<endl;
        }
    private:
        string m_name;
    };
    
    class website3factory{
    public:
        concretewebsite3 * getwebsite(string type){
            map<string,concretewebsite3 * >::iterator it;
            it = m_map.find(type);
            if(it == m_map.end()){
                m_map[type] = new concretewebsite3(type);
            }
            return m_map[type];
        }
    
        int getwebsitecount(){
            return m_map.size();
        }
    private:
        map<string,concretewebsite3 * > m_map;
    };
    int main(int argc, char* argv[])
    {
        // version 1 ,浪费对象
        //     website1 *p1 = new website1("movie");
        //     website1 *p2 = new website1("blog");
        //     website1 *p3 = new website1("music");
        //     p1->show();
        //     p2->show();
        //     p3->show();
    
        // version 2,共享了对象,但是数据还都是相同的,还需修改
        //     website2factory * fac = new website2factory;
        //     website2 * p1 = fac->getwebsite("blog");
        //     website2 * p2 = fac->getwebsite("blog");
        //     p1->show();
        //     p2->show();
        //     cout<<fac->getwebsitecount()<<endl;
    
        //version 3,将user身份传递给给website的show函数,就是对共享的对象,分不同的身份,即实现了数据分离
        website3factory * fac = new website3factory;
        website3 * p1 = fac->getwebsite("blog");
        website3 * p2 = fac->getwebsite("blog");
        cout<<"the website count is "<<fac->getwebsitecount()<<endl;  //只有一个“blog”website产生,
        website3 * p3 = fac->getwebsite("movie");
        website3 * p4 = fac->getwebsite("music");
        cout<<"the website count is "<<fac->getwebsitecount()<<endl;  // 1个“blog” 1个“movie” 1个“music”
        User user1("xiaowang");
        User user2("xiaohong");
        User user3("xiaohei");
        User user4("xiaogang");
        p1->show(user1);
        p2->show(user2);
        p3->show(user3);
        p4->show(user4);
        
        return 0;
    }
     

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

            棋子的定义,当然棋子的属性除了颜色和位置,还有其他的,这里略去。这两个属性足以说明问题。

    复制代码
    #include <iostream>
    #include <vector>
    #include <string>
    
    
    enum PieceColor {BLACK,WHITE};
    using namespace std;
    
    class Pos
    {
    public:
        Pos(int x,int y):m_x(x),m_y(y)
        {
        
        }
        int getX()
        {
            return m_x;
        }
        int getY()
        {
            return m_y;
        }
    private:
        int m_x;
        int m_y;
    };
    
    class Piece
    {
    public:
        Piece(PieceColor color,Pos pos):m_color(color),m_pos(pos){};
        ~Piece() {}
        virtual void Draw() {}
    protected:
        PieceColor m_color;
        Pos m_pos;
        
    };
    
    class WhitePiece : public Piece
    {
    public:
        WhitePiece(PieceColor color, Pos pos):Piece(color,pos){}
        ~WhitePiece();
        virtual void Draw() {
            cout << "draw a white piece" << endl;
        }
    };
    
    class BlackPiece:public Piece
    {
    public:
        BlackPiece(PieceColor color,Pos pos):Piece(color,pos){}
        ~BlackPiece();
        virtual void Draw(){
    
        cout << "draw a black piece" <<endl;
    
        }
    };
    
    class PieceBoard
    {
    public:
        PieceBoard(string black,string white):m_blackName(black),m_whiteName(white)
        {
        
        }
        ~PieceBoard() {
            Clear();
        }
        void SetPiece(PieceColor color,Pos pos)
        {
            Piece * piece = NULL;
            if(color == BLACK)
            {
                piece = new BlackPiece(color,pos);
                std::cout << m_blackName << "在位置(" << pos.getX() << ","<<pos.getY() <<")" <<endl ;
                piece->Draw();
                m_pieceArray.push_back(piece);
            }
            else
            {
                piece = new WhitePiece(color,pos);
                std::cout << m_whiteName << "在位置(" << pos.getX() << ","<<pos.getY() <<")" <<endl;
                piece->Draw();
                m_pieceArray.push_back(piece);
            }
        }
        void Clear()
        {
            int size = m_pieceArray.size();
            for(int i = 0; i < size ; i++)
                delete m_pieceArray[i];
        }
    private:
        std::vector<Piece*> m_pieceArray;
        std::string m_blackName;
        std::string m_whiteName;
    };
    复制代码

    主函数:

    复制代码
    #include "flyweight.h"
    int main()
    {
        PieceBoard pieceBoard("A","B");
        pieceBoard.SetPiece(BLACK,Pos(4,4));
        pieceBoard.SetPiece(WHITE,Pos(16,6));
    
        system("pause");
        return 0;
    }
    复制代码

     可以发现,棋盘的容器中存放了已下的棋子,而每个棋子包含棋子的所有属性。一盘棋往往需要含上百颗棋子,采用上面这种实现,占用的空间太大了。如何改进呢?用享元模式。其定义为:运用共享技术有效地支持大量细粒度的对象。

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

           关注PieceBoard 的容器,之前是vector<Piece*> m_vecPiece,现在是vector<PiecePos> m_vecPos。这里是关键。

           棋子的新定义,只包含内在属性:

    复制代码
    #include <iostream>
    #include <vector>
    #include <string>
    
    
    enum PieceColor {BLACK,WHITE};
    using namespace std;
    
    class Pos
    {
    public:
        Pos(int x,int y):m_x(x),m_y(y)
        {
        
        }
        int getX()
        {
            return m_x;
        }
        int getY()
        {
            return m_y;
        }
    private:
        int m_x;
        int m_y;
    };
    
    class Piece
    {
    public:
        Piece(PieceColor color):m_color(color){};
        ~Piece() {}
        virtual void Draw() {}
    protected:
        PieceColor m_color;
        
    };
    
    class WhitePiece : public Piece
    {
    public:
        WhitePiece(PieceColor color):Piece(color){}
        ~WhitePiece();
        virtual void Draw() {
            cout << "draw a white piece" << endl;
        }
    };
    
    class BlackPiece:public Piece
    {
    public:
        BlackPiece(PieceColor color):Piece(color){}
        ~BlackPiece();
        virtual void Draw(){
    
        cout << "draw a black piece" <<endl;
    
        }
    };
    
    class PieceBoard
    {
    public:
        PieceBoard(string black,string white):m_blackName(black),m_whiteName(white)
        {
        
        }
        ~PieceBoard() {
            Clear();
        }
        void SetPiece(PieceColor color,Pos pos)
        {
            Piece * piece = NULL;
            if(color == BLACK)
            {
                piece = new BlackPiece(color);
                std::cout << m_blackName << "在位置(" << pos.getX() << ","<<pos.getY() <<")" <<endl ;
                piece->Draw();
                m_blackPosArray.push_back(pos);
            }
            else
            {
                piece = new WhitePiece(color);
                std::cout << m_whiteName << "在位置(" << pos.getX() << ","<<pos.getY() <<")" <<endl;
                piece->Draw();
                m_whitePosArray.push_back(pos);
            }
        }
        void Clear()
        {
            //int size = m_pieceArray.size();
            //for(int i = 0; i < size ; i++)
            //    delete m_pieceArray[i];
        }
    private:
        std::vector<Pos> m_whitePosArray;
        std::vector<Pos> m_blackPosArray;
        std::string m_blackName;
        std::string m_whiteName;
    };
    复制代码

    主函数:

    复制代码
    #include "flyweight.h"
    int main()
    {
        PieceBoard pieceBoard("A","B");
        pieceBoard.SetPiece(BLACK,Pos(4,4));
        pieceBoard.SetPiece(WHITE,Pos(16,6));
    
        system("pause");
        return 0;
    }
     
    转载自:http://www.cnblogs.com/onlycxue/p/3487863.html
  • 相关阅读:
    集群架构搭建
    THUWC2019 游记
    【集训队互测2015】未来程序·改
    [NOIP2014普及组T1]珠心算测验
    [CF912D]Fishes
    [POJ2409]Let it Bead
    golang 统计系统测试覆盖率
    tcpdump常用方法
    数学闯关引发的思考
    linux lsof常用方法
  • 原文地址:https://www.cnblogs.com/xiumukediao/p/4637161.html
Copyright © 2011-2022 走看看