Structural.Flyweight(结构型模式—享元模式)

思考享元模式

  ①享元模式的本质:分离与共享。享元模式的关键在于分离变与不变,把不变部分作为享元对象的内部状态,而变化部分则作为外部状态,由外部来维护.这样享元对象就能够被共享,从而减少对象的数量,并节省大量的内存空间。

  ②享元模式的变与不变:为什么在一个地方要预留接口,一个常见的原因是这里存在变化,可能在今后需要扩展或改变己有的实现,而预留接口作为“可插入性的保证”

  ③享元对象:又有共享(ConcreteFlyweight)与不共享(UnsharedConcreteFlyweight)之分。不共享一般出现在和组合模式合用的情况,通常共享是叶子对象,一般不共享的部分是由共享部分组合而成,由于所有细粒度的叶子对象己经缓存了,那么缓存组合对象就没有什么意义。(如权限管理中某安全实体的“查看”和“修改”是可共享的,如果将“查看”和“修改”组合成“操作”权限的话,则操作”权限是不用缓存(共享)的,因为己经在细粒度上进行了缓存)。(见后面的例子)

【编程实验】围棋软件设计

        ①内部状态:每个围棋那么多的棋子,可设置为享元对象,有如下属性颜色、大小、形状。

        ②外部状态:棋子在棋盘中的位置。这是不可共享的。

//声明文件

//结构型模式:享元模式
//场景:围棋软件设计。
//内部状态——围棋棋子数量多,但分只为两类:白棋和黑棋。
//          有颜色、大小、形态等属性,是可共享的对象。
//外部状态——棋子在棋盘中的位置。

#include <iostream>
#include <string>
#include <map>

using namespace std;



//************************************享元类**************************
//非享元对象:UnsharedConcreteFlyweight(外部状态)
class CPos{
private:
	int X;
	int Y;
public:
	CPos(int x, int y);
	void SetX(int x);
	int GetX();
	void SetY(int y);
	int GetY();
};
//享元抽象类
class CWeight{
protected:
	string strColor;
public:
	virtual ~CWeight();
	void SetColor(string color);
	string GetColor();
	//显示棋子在棋盘中的位置
    //可以通过这个接口,将外部状态传入享元对象中
	virtual void Disp(CPos& pos) = 0;
};

//享元对象:ConcreteFlyweight(内部状态)
class CFly : public CWeight{
public:
	CFly(string color);
	~CFly();
	void Disp(CPos& pos);
};
//************************************享元工厂类**************************
class CChessFac{
private:
	static map<string, CWeight*> mpChess;
public:
	static CWeight* GetChess(string color);
	static void RemoveAll();
};

//实现文件

//************************************享元类**************************
//非享元对象:UnsharedConcreteFlyweight(外部状态)
CPos::CPos(int x, int y){X = x; Y = y;}
void CPos::SetX(int x){ X = x;}
int CPos::GetX(){return X;}
void CPos::SetY(int y){Y = y;}
int CPos::GetY(){return Y;}
//享元抽象类
CWeight::~CWeight(){cout << "~CWeight" << endl;}
void CWeight::SetColor(string color){strColor = color;}
string CWeight::GetColor(){return strColor;}


//享元对象:ConcreteFlyweight(内部状态)
CFly::CFly(string color){SetColor(color);}
CFly::~CFly(){cout << "~CFly" << endl; }
void CFly::Disp(CPos& pos)
{
	cout << "********************************************" << endl;
	cout << "Chess's Color : " << strColor << endl;
	cout << "Chess's Pos : (" << pos.GetX() << ", " << pos.GetY() << ")" << endl;
	cout << "********************************************" << endl << endl;
}
//************************************享元工厂类**************************
map<string, CWeight*> CChessFac::mpChess;
CWeight* CChessFac::GetChess(string color)
{
	CWeight* pChess = mpChess[color];
	if(pChess == NULL){
		pChess = new CFly(color);
		mpChess[color] = pChess;
	}
	return pChess;
}
void CChessFac::RemoveAll()
{
	cout << "Before deleting... size = " << mpChess.size() << endl;
	for(map<string, CWeight*>::iterator it = mpChess.begin(); it != mpChess.end(); ){
		cout << it->first << " : " << it->second << endl;
		CWeight* pWeight = it->second; 
		delete pWeight;
		it = mpChess.erase(it);
	}
	cout << "After deleted... size = " << mpChess.size() << endl;
}

//测试客户端

void main()
{
	CWeight* pChess1 = CChessFac::GetChess("Black");
	CWeight* pChess2 = CChessFac::GetChess("White");
	CWeight* pChess3 = CChessFac::GetChess("Black");

	cout << "pChess1 : " << pChess1 << endl;
	cout << "pChess2 : " << pChess2 << endl;
	cout << "pChess3 : " << pChess3 << endl;

	pChess1->Disp(CPos(10,10));
	pChess2->Disp(CPos(20,20));
	pChess3->Disp(CPos(30,30));

	CChessFac::RemoveAll();
}

猜你喜欢

转载自blog.csdn.net/KnightOnHourse/article/details/80003085
今日推荐