享元模式 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

你可能感兴趣的:(flyweight)