IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++常见设计模式之享元模式 -> 正文阅读

[C++知识库]C++常见设计模式之享元模式

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

//棋子颜色
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("鸟鸟","雀雀");

	pieceboard.SetPiece(BLACK,PiecePos(0,0));
	pieceboard.SetPiece(WHITE,PiecePos(1,1));
	pieceboard.SetPiece(BLACK,PiecePos(2,2));
	pieceboard.SetPiece(WHITE,PiecePos(3,3));

	return 0;
}

在这里插入图片描述
2、
可以发现 棋盘的容器中存放了已下的棋子,而每个棋子包含棋子的所有属性,一盘棋往往需要含上百颗棋子,采用上面的这种实现,占用的空间太大了,如何改进呢?用享元模式, 其定义为:运用共享技术有效的支持大量细粒度对象。在围棋中棋子就是大量细粒度对象,其属性有内在的 颜色 ,形状等,也有外在的,比如在棋盘上的位置,内在的属性是可以共享的,区分在于外在的属性 ,因此可以这样设计,只需定义两个棋子对象,一颗黑棋 ,一颗白棋,这两个对象含棋子的内在属性 ,棋子的外在属性即在容器上的位置可以提取出来,放在单独的容器中。相比之前的方案,现在容器中仅仅存放了位置属性 而原来的则是棋子对象,显然,现在的方案大大减少了,对于空间的需求。

关注容器,之前是 vector<Piece*>m_vecPiece ,现在是vector<PiecePos>m_vecPos,这里是关键。棋子新定义,只包含内在属性。

//棋子定义
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<<"绘制一颗黑棋"<<endl;
	}
};
	
class WhitePiece :public Piece
{
public:
	WhitePiece(PieceColor color): Piece(color){}

	~WhitePiece()
	{

	}

	void Draw()
	{
		cout<<"绘制一颗白棋"<<endl;
	}
};
	
//棋盘的定义
class PieceBoard
{
private:
	vector<PiecePos>m_vecPos; //棋子的位置

	BlackPiece *m_blackPiece; //黑棋棋子
	WhitePiece *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) //一颗黑棋也没有 需要new一颗黑棋 以后的黑棋除了位置 跟这颗黑棋没有差别 不需要在new 直接返回这颗黑棋对象即可
				m_blackPiece = new BlackPiece(color);

			cout<<m_blackName<<"在位置("<<pos.x<<','<<pos.y<<")";
			m_blackPiece->Draw(); //在棋盘上绘制出黑棋
		}
		else
		{
			if(m_whitePiece == NULL) //一颗白棋也没有 需要new一颗白棋
				m_whitePiece = new WhitePiece(color);

			cout<<m_whiteName<<"在位置("<<pos.x<<','<<pos.y<<")";
			m_whitePiece->Draw(); //在棋盘上绘制出白棋
		}
		m_vecPos.push_back(pos); //放入容器中
	}

};

主函数测试过程一样,不在赘述。
3、优点
享元模式可以避免大量非常相似对象的开销。在程序设计时,有时需要生成大量细粒度的类实例来表示数据。如果能发现这些实例数据除了几个参数外基本都是相同的,使用享元模式就可以大幅度地减少对象的数量。
4、使用场合
Flyweight模式的有效性很大程度上取决于如何使用它以及在何处使用它。当以下条件满足时,我们就可以使用享元模式了。
1)一个应用程序使用了大量的对象;
2)完全由于使用大量的对象,造成很大的存储开销;
3)对象的大多数状态都可变为外部状态;
4)如果删除对象的外部状态,那么可以用相对较少的共享对象取代很多组对象。
5、总结
使用享元模式可以避免大量相似对象的开销,减小了空间消耗;而空间的消耗是由以下几个因素决定的:实例对象减少的数目;对象内部状态的数目;对象内部状态越多,消耗的空间也会越少;外部状态是计算的还是存储的;由于外部状态可能需要存储,如果外部状态存储起来,那么空间的节省就不会太多。

部分内容参考于:https://www.cnblogs.com/ring1992/p/9593235.html
https://blog.csdn.net/wuzhekai1985/article/details/6670298

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:39:53  更:2021-11-15 15:41:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 6:19:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码