`
caiwb1990
  • 浏览: 315153 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

设计模式(11)- 享元模式

阅读更多
    举个围棋的例子,围棋的棋盘共有361格,即可放361个棋子。现在要实现一个围棋程序,该怎么办呢?首先要考虑的是棋子棋盘的实现,可以定义一个棋子的类,成员变量包括棋子的颜色、形状、位置等信息,另外再定义一个棋盘的类,成员变量中有个容器,用于存放棋子的对象。下面给出代码表示:
    棋子的定义,当然棋子的属性除了颜色和位置,还有其他的,这里略去。这两个属性足以说明问题。


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




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


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

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

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

棋子的新定义,只包含内在属性:
//棋子颜色
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<<"绘制一颗黑棋\n"; }
};
class WhitePiece: public Piece
{
public:
	WhitePiece(PieceColor color): Piece(color) {}
	~WhitePiece() {}
	void Draw() { cout<<"绘制一颗白棋\n";}
};


相应棋盘的定义为:

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);
	}
};

  • 大小: 6.2 KB
分享到:
评论

相关推荐

    设计模式--享元模式

    设计模式--享元模式

    JAVA-设计模式-结构型模式-享元模式

    JAVA-设计模式-结构型模式-享元模式

    设计模式精解-GoF-23种设计模式解析--附C++源代码

    - 享元模式(Flyweight):使用共享对象,有效地支持大量细粒度的对象。 3. **行为型模式**:这类模式关注对象之间的责任分配。 - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起...

    java常用设计模式-享元模式

    java常用设计模式-享元模式

    java基础设计模式模式 - 享元模式.7z

    享元模式是一种优化资源使用的软件设计模式,尤其适用于对象创建成本较高或系统内存有限的场景。在Java编程中,享元模式通过共享已有对象来减少内存中的对象数量,从而提高性能。这种模式的核心是实现细粒度对象的...

    c++设计模式-结构型模式-享元模式

    c++设计模式-结构型模式-享元模式;qt工程;c++简单源码; 享元(Flyweight)模式的定义:运用共享技术来有效地支持大量细粒度对象的复用。它通过共享已经存在的对象来大幅度减少需要创建的对象数量、避免大量相似类...

    6.设计模式-享元模式1

    设计模式-享元模式 设计模式是软件设计中的一种解决方案,旨在提高代码的可维护性、灵活性和可重用性。享元模式(Flyweight Pattern)是结构型模式的一种,主要用于减少大量相似对象的内存占用,提高系统的性能和...

    设计模式-享元模式(讲解及其实现代码)

    享元模式是一种结构型设计模式,它通过共享已有对象来减少内存中对象的数量,从而达到降低系统内存占用、提高性能的目的。在软件工程中,当系统中存在大量相似或重复的对象时,享元模式尤为适用。 享元模式的核心是...

    设计模式课件大全

    设计模式09-外观模式、享元模式 设计模式10-代理模式、结构型模式大复习 设计模式11-行为模式-责任链、命令模式 设计模式12-解释器模式 设计模式13-迭代器模式 设计模式14-中介者模式、备忘录模式 设计模式15-观察者...

    java设计模式---诙谐易懂版

    根据给定文件内容,以下是关于Java设计模式的知识点说明: 1. 策略模式(Strategy Pattern)是一种行为设计模式,允许在运行时选择算法的行为。策略模式的意图是定义一系列算法,将每个算法封装起来,并使它们可以...

    设计模式精解-GoF23种设计模式解析附C++实现源码

    - 享元模式(Flyweight):运用共享技术有效地支持大量细粒度的对象。 3. 行为型模式(Behavioral Patterns): - 责任链模式(Chain of Responsibility):避免将请求的发送者和接收者耦合在一起,使得多个对象...

    设计模式学习笔记--Flyweight享元模式.docx

    享元模式是一种设计模式,属于构造型模式,其主要目的是减少对象的数量,通过共享大量相似对象的内部状态来节省内存。这种模式在处理大量细粒度对象时特别有用,能够有效地提高系统的性能。 享元模式的核心是...

    Java设计模式----通俗易懂版

    这个资源"Java设计模式----通俗易懂版"显然是一个专门针对初学者或需要深入理解设计模式的开发者编写的指南。作者以形象生动的例子解释了23种经典的Java设计模式,使得复杂的概念变得更加易于理解。 首先,我们要...

    设计模式----命令模式

    享元模式则是一种结构型设计模式,它能通过共享技术有效地支持大量细粒度的对象。当系统中存在大量相似对象时,享元模式可以极大地减少内存的占用。享元模式通常与Flyweight接口、Concrete Flyweight(具体享元)、...

    设计模式精解-GoF 23种设计模式

    11. **享元模式**:运用共享技术有效地支持大量细粒度的对象,减少内存占用。 12. **外观模式**:为子系统提供一个统一的接口,使得子系统更容易被使用。 13. **代理模式**:为其他对象提供一种代理以控制对这个...

    设计模式专题之(十二)享元模式---设计模式享元模式示例代码(python--c++)

    享元模式是一种结构型设计模式,它通过共享已有对象来减少内存中对象的数量,从而达到提高系统性能的目的。在大型软件系统中,特别是在处理大量相似对象时,享元模式能够有效地减少内存开销,提高系统运行效率。在这...

    设计模式的享元模式的例子

    享元模式是软件设计模式中的一种结构型模式,它的主要目的是通过共享大量细粒度对象来减少内存的使用,提高系统性能。在许多场景下,尤其是处理大量相似对象时,享元模式能显著减少内存开销。这个压缩包文件...

    新版设计模式手册 - C#设计模式(第二版)

    《新版设计模式手册 - C#设计模式(第二版)》是一部深入探讨C#编程中设计模式的权威指南,尤其适合已经有一定C#基础并希望提升软件设计能力的开发者阅读。设计模式是解决软件开发中常见问题的经验总结,是软件工程的...

Global site tag (gtag.js) - Google Analytics