C++享元模式详解

 更新时间:2021年09月14日 08:41:15   作者:酸菜。  
这篇文章主要为大家详细介绍了C++设计模式之享元模式Flyweight,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

未引入享元模式

#include <iostream>
#include <list>
#include <map>
using namespace std;

enum class  EnumColor //棋子类型
{
	Black, //黑
	White  //白
};
struct Position //棋子位置
{
	int m_x;
	int m_y;
	Position(int tmpx, int tmpy) :m_x(tmpx), m_y(tmpy) {} //构造函数			
};
/*棋子类*/
class Piece 
{
public:
	//构造函数
	Piece(EnumColor tmpcolor, Position tmppos) :m_color(tmpcolor), m_pos(tmppos){}
	//棋子的绘制
	void draw()
	{
		if(m_color == EnumColor::Black)
		{
			cout << "在位置:(" << m_pos.m_x << "," << m_pos.m_y << ")处绘制了一个黑色棋子!" << endl;
		}
		else
		{
			cout << "在位置:(" << m_pos.m_x << "," << m_pos.m_y << ")处绘制了一个白色棋子!" << endl;
		}
	}
private:
	EnumColor m_color; //棋子颜色
	Position m_pos; //棋子位置
};
int main()
{
	//检测内存泄漏
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	Piece* p_piece1 = new Piece(EnumColor::Black, Position(3, 3)); //黑色落子到3,3位置
	p_piece1->draw();
	Piece* p_piece2 = new Piece(EnumColor::White, Position(5, 5)); //白色落子到5,5位置
	p_piece2->draw();
	Piece* p_piece3 = new Piece(EnumColor::Black, Position(4, 6)); //黑色落子到4,6位置
	p_piece3->draw();
	Piece* p_piece4 = new Piece(EnumColor::White, Position(5, 7)); //白色落子到5,7位置
	p_piece4->draw();
	//释放资源
	delete p_piece1;
	delete p_piece2;
	delete p_piece3;
	delete p_piece4;
	return 0;
}

在这里插入图片描述

对于上面的例程来说,棋子的类型无非就是两种,黑和白,在实际的下棋过程当中,只有位置是不一样的,但是却衍生出了多个具有相似度的对象,我们能否进行改造一下,比如,对象只有两个,黑和白,在实际的运转的时候,改变他们的位置就可以了,这样就不用new很多给相似的对象出来了。下面我们进行改造一下。引入享元模式。

引入享元模式

#include <iostream>
#include <list>
#include <map>
using namespace std;

enum EnumColor //棋子类型
{
	Black, //黑
	White  //白
};
struct Position //棋子位置
{
	int m_x;
	int m_y;
	Position(int tmpx, int tmpy) :m_x(tmpx), m_y(tmpy) {} //构造函数			
};
class Piece //棋子抽象类
{
public:
	virtual ~Piece() {} 
public:
	virtual void draw(Position tmppos) = 0;
};

class BlackPiece :public Piece //黑色棋子
{
public:
	virtual void draw(Position tmppos)
	{
		cout << "在位置:(" << tmppos.m_x << "," << tmppos.m_y << ")处绘制了一个黑色棋子!" << endl;
	}
};

class WhitePiece :public Piece //白色棋子
{
public:
	virtual void draw(Position tmppos)
	{
		cout << "在位置:(" << tmppos.m_x << "," << tmppos.m_y << ")处绘制了一个白色棋子!" << endl;
	}
};

class pieceFactory //创建棋子的工厂
{
public:
	virtual ~pieceFactory()
	{
		//释放内存
		for(auto iter = m_FlyWeightMap.begin(); iter != m_FlyWeightMap.end(); ++iter)
		{
			Piece* tmpfw = iter->second;
			delete tmpfw;
		}
		m_FlyWeightMap.clear(); 
	}
	//获取享元对象,也就是获取被共享的棋子对象
	Piece* getFlyWeight(EnumColor tmpcolor)
	{
		auto iter = m_FlyWeightMap.find(tmpcolor);
		if(iter == m_FlyWeightMap.end())
		{
			//没有该享元对象,那么就创建出来
			Piece* tmpfw = nullptr;
			if(tmpcolor == Black) //黑子
			{
				tmpfw = new BlackPiece();
			}
			else //白子
			{
				tmpfw = new WhitePiece();
			}
			//以棋子颜色枚举值作为key,增加条目到map中
			m_FlyWeightMap.insert(make_pair(tmpcolor, tmpfw)); 
			return tmpfw;
		}
		else
		{
			return iter->second;
		}
	}
private:
	std::map<EnumColor, Piece*> m_FlyWeightMap; //享元池,用map容器来保存所有的享元对象,一共就两个享元对象(黑色棋子一个,白色棋子一个)
};
int main()
{
	//检测内存泄漏
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
	pieceFactory* pfactory = new pieceFactory();
	Piece* p_piece1 = pfactory->getFlyWeight(Black);
	p_piece1->draw(Position(3, 3));  //黑子落子到3,3位置
	Piece* p_piece2 = pfactory->getFlyWeight(White);
	p_piece2->draw(Position(5, 5));  //白子落子到5,5位置
	Piece* p_piece3 = pfactory->getFlyWeight(Black);
	p_piece3->draw(Position(4, 6));  //黑子落子到4,6位置
	Piece* p_piece4 = pfactory->getFlyWeight(White);
	p_piece4->draw(Position(5, 7));  //白子落子到5,7位置
	//释放资源
	delete  pfactory;
	return 0;
}

在这里插入图片描述

在这里插入图片描述

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • MyBatis Plus更新对象无法设空值解决方案

    MyBatis Plus更新对象无法设空值解决方案

    这篇文章主要介绍了MyBatis Plus更新对象无法设空值解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • 详解Java单元测试之Junit框架使用教程

    详解Java单元测试之Junit框架使用教程

    单元测试就是针对最小的功能单元编写测试代码,Junit是使用Java语言实现的单元测试框架,它是开源的,Java开发者都应当学习并使用Junit编写单元测试。本文就来讲讲Junit框架的使用教程,需要的可以参考一下
    2022-05-05
  • Java模拟实现斗地主的洗牌和发牌

    Java模拟实现斗地主的洗牌和发牌

    这篇文章主要为大家详细介绍了Java模拟实现斗地主的洗牌和发牌,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • springboot中如何通过main方法调用service或dao

    springboot中如何通过main方法调用service或dao

    这篇文章主要介绍了springboot中如何通过main方法调用service或dao,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-02-02
  • Java 通过mave命令下载jar包的示例代码

    Java 通过mave命令下载jar包的示例代码

    这篇文章主要介绍了Java 通过mave命令下载jar的示例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-11-11
  • Java实现网络资源的单线程下载

    Java实现网络资源的单线程下载

    这篇文章主要为大家详细介绍了如何利用Java语言实现在一个线程中完成网络资源的下载,文中的实现步骤讲解详细,感兴趣的可以尝试下
    2022-10-10
  • SpringBoot如何使用TestEntityManager进行JPA集成测试

    SpringBoot如何使用TestEntityManager进行JPA集成测试

    TestEntityManager是Spring Framework提供的一个测试框架,它可以帮助我们进行 JPA 集成测试,在本文中,我们将介绍如何使用 TestEntityManager 进行 JPA 集成测试,感兴趣的跟着小编一起来学习吧
    2023-06-06
  • C++实现扫雷游戏示例讲解

    C++实现扫雷游戏示例讲解

    这篇文章主要介绍了C++实现扫雷游戏示例讲解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-08-08
  • Java并发编程中的生产者与消费者模型简述

    Java并发编程中的生产者与消费者模型简述

    这篇文章主要介绍了Java并发编程中的生产者与消费者模型简述,多线程并发是Java编程中最终要的部分之一,需要的朋友可以参考下
    2015-07-07
  • javassist使用指南

    javassist使用指南

    这篇文章主要介绍了javassist的使用方法,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07

最新评论