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

浙公网安备 33010602011771号