C++11 设计模式4. 抽象工厂(Abstract Factory)模式

news2024/12/22 19:18:49

问题的提出

从前面我们已经使用了工厂方法模式 解决了一些问题。

现在 策划又提出了新的需求:对于各个怪物,在不同的场景下,怪物的面板数值会发生变化,

    //怪物分类:亡灵类,元素类,机械类
    //战斗场景分类:沼泽地区,山脉地区,城镇。

那么就有9类怪物====>沼泽地亡灵类、元素类、机械类,山脉地区亡灵类、元素类、机械类,城镇中的亡灵类、元素类、机械类
    //工厂方法模式:一个工厂创建一种类怪物。我们就要创建9个工厂了。

抽象模式的核心思想

    //但如果一个工厂子类能够创建不止一种而是多种具有相同规则的怪物对象,那么就可以有效的减少所创建的工厂子类数量,这就是抽象工厂模式的核心思想。
 

两个概念:a)产品等级结构   b)产品族

在这里,我们先要弄清楚 两个概念:a)产品等级结构   b)产品族
    //抽象工厂模式是按照产品族来生产产品(产地相同的用一个工厂来生产)——一个地点有一个工厂,该工厂负责生产本产地的所有产品。
 

代码实现

第一步:肯定是先将9个类先弄出来

第二步:第二步,定义一个抽象工厂类

    //所有工厂类的父类

第三步:具体沼泽地区的工厂

#include <iostream>
using namespace std;

namespace _namespace1 {

	//第一步,定义9个怪物和其父类
	//怪物父类
	class Monster
	{
	public:
		//构造函数
		Monster(int life, int magic, int attack) :m_life(life), m_magic(magic), m_attack(attack) {}
		virtual ~Monster() {} //做父类时析构函数应该为虚函数

	protected://可能被子类访问的成员,所以用protected修饰
		//怪物属性
		int m_life; //生命值
		int m_magic; //魔法值
		int m_attack; //攻击力
	};

	//沼泽亡灵类怪物
	class M_Undead_Swamp :public Monster
	{
	public:
		M_Undead_Swamp(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个沼泽的亡灵类怪物来到了这个世界" << endl;
		}
	};
	//沼泽元素类怪物
	class M_Element_Swamp :public Monster
	{
	public:
		M_Element_Swamp(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个沼泽的元素类怪物来到了这个世界" << endl;
		}
	};
	//沼泽机械类怪物
	class M_Mechanic_Swamp :public Monster
	{
	public:
		M_Mechanic_Swamp(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个沼泽的机械类怪物来到了这个世界" << endl;
		}
	};
	//--------------------------
	//山脉亡灵类怪物
	class M_Undead_Mountain :public Monster
	{
	public:
		M_Undead_Mountain(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个山脉的亡灵类怪物来到了这个世界" << endl;
		}
	};
	//山脉元素类怪物
	class M_Element_Mountain :public Monster
	{
	public:
		M_Element_Mountain(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个山脉的元素类怪物来到了这个世界" << endl;
		}
	};
	//山脉机械类怪物
	class M_Mechanic_Mountain :public Monster
	{
	public:
		M_Mechanic_Mountain(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个山脉的机械类怪物来到了这个世界" << endl;
		}
	};
	//--------------------------
	//城镇亡灵类怪物
	class M_Undead_Town :public Monster
	{
	public:
		M_Undead_Town(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个城镇的亡灵类怪物来到了这个世界" << endl;
		}
	};
	//城镇元素类怪物
	class M_Element_Town :public Monster
	{
	public:
		M_Element_Town(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个城镇的元素类怪物来到了这个世界" << endl;
		}
	};
	//城镇机械类怪物
	class M_Mechanic_Town :public Monster
	{
	public:
		M_Mechanic_Town(int life, int magic, int attack) :Monster(life, magic, attack)
		{
			cout << "一个城镇的机械类怪物来到了这个世界" << endl;
		}
	};


	//如上已经把9个怪物定义出来了
	//第二步,定义一个抽象工厂类
	//所有工厂类的父类
	class M_ParFactory
	{
	public:
		virtual Monster* createMonster_Undead() = 0; //创建亡灵类怪物
		virtual Monster* createMonster_Element() = 0; //创建元素类怪物
		virtual Monster* createMonster_Mechanic() = 0; //创建机械类怪物
		virtual ~M_ParFactory() {} //做父类时析构函数应该为虚函数
	};

	//沼泽地区的工厂
	class M_Factory_Swamp :public M_ParFactory
	{
	public:
		virtual Monster* createMonster_Undead()
		{
			return new M_Undead_Swamp(300, 50, 120); //创建沼泽亡灵类怪物
		}
		virtual Monster* createMonster_Element()
		{
			return new M_Element_Swamp(200, 80, 110); //创建沼泽元素类怪物
		}
		virtual Monster* createMonster_Mechanic()
		{
			return new M_Mechanic_Swamp(400, 0, 90); //创建沼泽机械类怪物
		}
	};
	//--------------------------
	//山脉地区的工厂
	class M_Factory_Mountain :public M_ParFactory
	{
	public:
		virtual Monster* createMonster_Undead()
		{
			return new M_Undead_Mountain(300, 50, 80); //创建山脉亡灵类怪物
		}
		virtual Monster* createMonster_Element()
		{
			return new M_Element_Mountain(200, 80, 100); //创建山脉元素类怪物
		}
		virtual Monster* createMonster_Mechanic()
		{
			return new M_Mechanic_Mountain(600, 0, 110); //创建山脉机械类怪物
		}
	};
	//--------------------------
	//城镇的工厂
	class M_Factory_Town :public M_ParFactory
	{
	public:
		virtual Monster* createMonster_Undead()
		{
			return new M_Undead_Town(300, 50, 80); //创建城镇亡灵类怪物
		}
		virtual Monster* createMonster_Element()
		{
			return new M_Element_Town(200, 80, 100); //创建城镇元素类怪物
		}
		virtual Monster* createMonster_Mechanic()
		{
			return new M_Mechanic_Town(400, 0, 110); //创建城镇机械类怪物
		}
	};


}



int main() {

	_namespace1::M_ParFactory* p_mou_fy = new _namespace1::M_Factory_Mountain(); //多态工厂,山脉地区的工厂
	_namespace1::Monster* pM1 = p_mou_fy->createMonster_Element(); //创建山脉地区的元素类怪物

	_namespace1::M_ParFactory* p_twn_fy = new _namespace1::M_Factory_Town(); //多态工厂,城镇的工厂
	_namespace1::Monster* pM2 = p_twn_fy->createMonster_Undead(); //创建城镇地区的亡灵类怪物
	_namespace1::Monster* pM3 = p_twn_fy->createMonster_Mechanic(); //创建城镇地区的机械类怪物

	//释放资源
	//释放工厂
	delete p_mou_fy;
	delete p_twn_fy;

	delete pM1;
	delete pM2;
	delete pM3;
	return 0;
}

第二个例子:

不同厂商生产不同部件范例
    //芭比娃娃:身体(包括头、颈部、躯干、四肢)、衣服、鞋子
    //中国,日本,美国 厂商
    //要求:制作两个芭比娃娃,第一个:身体,衣服,鞋子,全部采用中国厂商制造的部件。
                            //第二个:身体采用中国厂商,衣服部件采用日本厂商,鞋子部件采用美国厂商。
    //类的设计思路:
    //a)将身体,衣服,鞋子 这三个部件实现为抽象类。
    //b)实现一个抽象工厂,分别用来生产身体、衣服、鞋子这三个部件。
    //c)针对不同厂商的每个部件实现具体的类以及每个厂商所代表的具体工厂。

namespace _nmsp3
{
	//身体抽象类
	class Body
	{
	public:
		virtual void getName() = 0;
		virtual ~Body() {}
	};

	//衣服抽象类
	class Clothes
	{
	public:
		virtual void getName() = 0;
		virtual ~Clothes() {}
	};

	//鞋子抽象类
	class Shoes
	{
	public:
		virtual void getName() = 0;
		virtual ~Shoes() {}
	};

	//---------------------------
	//抽象工厂类
	class AbstractFactory
	{
	public:
		//所创建的部件应该稳定的保持这三个部件,才适合抽象工厂模式
		virtual Body* createBody() = 0; //创建身体
		virtual Clothes* createClothes() = 0; //创建衣服
		virtual Shoes* createShoes() = 0; //创建鞋子
		virtual ~AbstractFactory() {}
	};

	//---------------------------
	//芭比娃娃类
	class BarbieDoll
	{
	public:
		//构造函数
		BarbieDoll(Body* tmpbody, Clothes* tmpclothes, Shoes* tmpshoes)
		{
			body = tmpbody;
			clothes = tmpclothes;
			shoes = tmpshoes;
		}

		void Assemble() //组装芭比娃娃
		{
			cout << "成功组装了一个芭比娃娃:" << endl;
			body->getName();
			clothes->getName();
			shoes->getName();
		}

	private:
		Body* body;
		Clothes* clothes;
		Shoes* shoes;
	};
	//---------------------------
	//中国厂商实现的三个部件
	class China_Body :public Body
	{
	public:
		virtual void getName()
		{
			cout << "中国厂商产的_身体部件" << endl;
		}
	};
	class China_Clothes :public Clothes
	{
	public:
		virtual void getName()
		{
			cout << "中国厂商产的_衣服部件" << endl;
		}
	};
	class China_Shoes :public Shoes
	{
	public:
		virtual void getName()
		{
			cout << "中国厂商产的_鞋子部件" << endl;
		}
	};
	//创建一个中国工厂
	class ChinaFactory : public AbstractFactory
	{
	public:
		virtual Body* createBody()
		{
			return new China_Body;
		}
		virtual Clothes* createClothes()
		{
			return new China_Clothes;
		}
		virtual Shoes* createShoes()
		{
			return new China_Shoes;
		}
	};
	//---------------------------
	//日本厂商实现的三个部件
	class Japan_Body :public Body
	{
	public:
		virtual void getName()
		{
			cout << "日本厂商产的_身体部件" << endl;
		}
	};
	class Japan_Clothes :public Clothes
	{
	public:
		virtual void getName()
		{
			cout << "日本厂商产的_衣服部件" << endl;
		}
	};
	class Japan_Shoes :public Shoes
	{
	public:
		virtual void getName()
		{
			cout << "日本厂商产的_鞋子部件" << endl;
		}
	};
	//创建一个日本工厂
	class JapanFactory : public AbstractFactory
	{
	public:
		virtual Body* createBody()
		{
			return new Japan_Body;
		}
		virtual Clothes* createClothes()
		{
			return new Japan_Clothes;
		}
		virtual Shoes* createShoes()
		{
			return new Japan_Shoes;
		}
	};
	//---------------------------
	//美国厂商实现的三个部件
	class America_Body :public Body
	{
	public:
		virtual void getName()
		{
			cout << "美国厂商产的_身体部件" << endl;
		}
	};
	class America_Clothes :public Clothes
	{
	public:
		virtual void getName()
		{
			cout << "美国厂商产的_衣服部件" << endl;
		}
	};
	class America_Shoes :public Shoes
	{
	public:
		virtual void getName()
		{
			cout << "美国厂商产的_鞋子部件" << endl;
		}
	};
	//创建一个美国工厂
	class AmericaFactory : public AbstractFactory
	{
	public:
		virtual Body* createBody()
		{
			return new America_Body;
		}
		virtual Clothes* createClothes()
		{
			return new America_Clothes;
		}
		virtual Shoes* createShoes()
		{
			return new America_Shoes;
		}
	};
}


int main() {


	//创建第一个芭比娃娃------------
	//(1)创建一个中国工厂
	_nmsp3::AbstractFactory* pChinaFactory = new _nmsp3::ChinaFactory();
	//(2)创建中国产的各种部件
	_nmsp3::Body* pChinaBody = pChinaFactory->createBody();
	_nmsp3::Clothes* pChinaClothes = pChinaFactory->createClothes();
	_nmsp3::Shoes* pChinaShoes = pChinaFactory->createShoes();
	//(3)创建芭比娃娃
	_nmsp3::BarbieDoll* pbd1obj = new _nmsp3::BarbieDoll(pChinaBody, pChinaClothes, pChinaShoes);
	pbd1obj->Assemble(); //组装芭比娃娃

	cout << "-------------------------------------" << endl;
	//创建第二个芭比娃娃------------
	//(1)创建另外两个工厂:日本工厂,美国工厂
	_nmsp3::AbstractFactory* pJapanFactory = new _nmsp3::JapanFactory();
	_nmsp3::AbstractFactory* pAmericaFactory = new _nmsp3::AmericaFactory();
	//(2)创建中国产的身体部件,日本产的衣服部件,美国产的鞋子部件
	_nmsp3::Body* pChinaBody2 = pChinaFactory->createBody();
	_nmsp3::Clothes* pJapanClothes = pJapanFactory->createClothes();
	_nmsp3::Shoes* pAmericaShoes = pAmericaFactory->createShoes();
	//(3)创建芭比娃娃
	_nmsp3::BarbieDoll* pbd2obj = new _nmsp3::BarbieDoll(pChinaBody2, pJapanClothes, pAmericaShoes);
	pbd2obj->Assemble(); //组装芭比娃娃

	//最后记得释放内存----------------
	delete pbd1obj;
	delete pChinaShoes;
	delete pChinaClothes;
	delete pChinaBody;
	delete pChinaFactory;
	//------------
	delete pbd2obj;
	delete pAmericaShoes;
	delete pJapanClothes;
	delete pChinaBody2;
	delete pAmericaFactory;
	delete pJapanFactory;

	return 0;
}

工厂方法模式 和 抽象工厂模式的区别


    //工厂方法模式和抽象工厂模式区别:
    //a)工厂方法模式:一个工厂生产一个产品
    //b)抽象工厂模式:一个工厂生产多个产品(产品族)

    //抽象工厂模式的定义(实现意图):提供一个接口(AbstractFactory),
           //让该接口负责创建一系列相关或者相互依赖的对象(Body,Clothes,Shoes),而无需指定他们具体的类。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1592139.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity让地图素材遮挡人物

点击编辑/项目设置/图形&#xff0c;透明度排序模式设置自定义轴&#xff0c;透明度排序轴Y设置为1其他为0。 此时人物和地图素材的图层排序相等&#xff0c;当人物的高度大于地图素材时&#xff0c;人物则被遮挡。

使用ArrayList.removeAll(List list)导致的机器重启

背景 先说一下背景&#xff0c;博主所在的业务组有一个核心系统&#xff0c;需要同步两个不同数据源给过来的数据到redis中&#xff0c;但是每次同步之前需要过滤掉一部分数据&#xff0c;只存储剩下的数据。每次同步的数据与需要过滤掉的数据量级大概在0-100w的数据不等。 由…

【C语言】字符串函数和内存函数及其模拟实现

文章目录 前言 一、常见字符串库函数1.strlen函数2.长度不受限制的字符串函数2.1 strcpy2.2 strcat2.3 strcmp 3.长度受限制的字符串函数3.1 strncpy3.2 strncat3.3 strncmp 二、字符串查找函数strstrstrtok 三、strerror函数四、内存操作函数1.memcpy2.memmove3.memcmp 五、字…

Unity之Unity面试题(三)

内容将会持续更新&#xff0c;有错误的地方欢迎指正&#xff0c;谢谢! Unity之Unity面试题&#xff08;三&#xff09; TechX 坚持将创新的科技带给世界&#xff01; 拥有更好的学习体验 —— 不断努力&#xff0c;不断进步&#xff0c;不断探索 TechX —— 心探索、心进取…

简单工厂模式大解析:让代码创造更高效、更智能!

个人主页: danci_ &#x1f525;系列专栏&#xff1a;《设计模式》《MYSQL应用》 &#x1f4aa;&#x1f3fb; 制定明确可量化的目标&#xff0c;坚持默默的做事。 &#x1f680; 转载自热榜文章&#xff1a;探索设计模式的魅力&#xff1a;简单工厂模式 简单工厂模式&#x…

【零基础学数据结构】双向链表

1.双向链表的概念 1.1头节点 1.2带头双向循环链表 注意&#xff1a; 哨兵位创建后&#xff0c;首尾连接自己 1.3双链表的初始化 // 双向链表的初始化 void ListInit(ListNode** pphead) {// 给双链表创建一个哨兵位*pphead ListBuyNode(-1); } 2.双向链表的打印 // 双向…

PE文件的分析和构造超详细过程

本文详细讲述如何从0构造一个PE文件&#xff0c;运行该文件会弹出一个HelloPE的窗口 目录 预备知识 1. 构造DOS头IMAGE_DOS_HEADER 1.1 构造DOS_MZ头 1.2 构造DOS_STUB 2、构造PE头IMAGE_NT_HEADERS 248字节 2.1 signature 2.2 IMAGE_FILE_HEADER 2.3 IMAGE_OPTI…

MOS管电路的应用及注意事项

1,buck电路的上下桥死区时间多少合适 死区时间由驱动芯片控制的&#xff0c;外围电路增加阻容会导致上升沿时间变长 死区时间从单片机PWM到驱动电路再到MOS管的栅极都有一定的硬件延时&#xff0c;所以具体时间需要根据调试确定。 例如充电芯片的buck电路&#xff0c;有死区配置…

mysql8.0高可用集群架构实战

MySQL :: MySQL Shell 8.0 :: 7 MySQL InnoDB Cluster 基本概述 InnoDB Cluster是MySQL官方实现高可用读写分离的架构方案,其中包含以下组件 MySQL Group Replication,简称MGR,是MySQL的主从同步高可用方案,包括数据同步及角色选举Mysql Shell 是InnoDB Cluster的管理工具,用…

数据库系统概论(超详解!!!)第四节 数据库安全性

问题的提出&#xff1a; 数据库的一大特点是数据可以共享 数据共享必然带来数据库的安全性问题 数据库系统中的数据共享不能是无条件的共享。 1.数据库的安全概述 数据库的安全性是指保护数据库以防止不合法使用所造成的数据泄露、更改或破坏 。 系统安全保护措施是否有效…

基于ssm的土家风景文化管理平台(java源码+文档)

项目简介 土家风景文化管理平台实现了以下功能&#xff1a; 土家风景文化管理平台的主要使用者分为管理员&#xff1a;管理员使用本平台涉到的功能主要有&#xff1a;首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;景点分类管理&#xff0c;热门景点管理&#xf…

深度学习学习日记4.7

1.梯度下降 w 新 w旧 - 学习率梯度 训练的目的就是让 loss 减小 2.前向传播进行预测&#xff0c; 反向传播进行训练(每一个参数通过梯度下降进行更新参数)&#xff0c;(1前向传播 2求 loss 3反向传播 4梯度更新) 能够让损失下降的参数&#xff0c;就是更好的参数。 损失…

基于SSM物业管理系统

摘要 进入二十一世纪以来&#xff0c;计算机技术蓬勃发展&#xff0c;人们的生活发生了许多变化。很多时候人们不需要亲力亲为的做一些事情&#xff0c;通过网络即可完成以往需要花费很多时间的操作&#xff0c;这可以提升人们的生活质量。计算机技术对人们生活的改变不仅仅包…

单列模式1.0

单列模式 单例模式能保证某个类在程序中只存在唯⼀⼀份实例, ⽽不会创建出多个实例 1.饿汉模式 只要程序一启动就会立即创建出一个对象 class Signleton{private static Signleton instancenew Signleton();//防止在以后的代码中再创建对象&#xff0c;我们将构造方法private,…

FreeFileSync|本地自动备份设置教程,终于可以不用手动同步了

前言 昨天小白给各位小伙伴分享了FreeFileSync软件&#xff0c;由于篇幅过长&#xff0c;所以整个教程中并没有教小伙伴们如何设置自动同步的办法。 今天小白就来唠唠&#xff1a;如何让FreeFileSync自动同步。 教程分为几种&#xff1a; 开机自动同步 开机之后自动执行一次…

LeetCode617:合并二叉树

题目描述 给你两棵二叉树&#xff1a; root1 和 root2 。 想象一下&#xff0c;当你将其中一棵覆盖到另一棵之上时&#xff0c;两棵树上的一些节点将会重叠&#xff08;而另一些不会&#xff09;。你需要将这两棵树合并成一棵新二叉树。合并的规则是&#xff1a;如果两个节点重…

天地人和•大道不孤——卢禹舜中国画作品展在重庆美术馆隆重开幕

2024年4月12日&#xff0c;由中国国家画院、重庆市文化和旅游发展委员会主办&#xff0c;重庆美术馆&#xff08;重庆画院、重庆国画院&#xff09;、北京八荒锦绣美术馆、中国国际文化交流基金会卢禹舜艺术基金承办的“天地人和•大道不孤——卢禹舜中国画作品展”开幕式在重庆…

SF58-ASEMI适配器二极管SF58

编辑&#xff1a;ll SF58-ASEMI适配器二极管SF58 型号&#xff1a;SF58 品牌&#xff1a;ASEMI 封装&#xff1a;DO-27 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;5A 最大循环峰值反向电压&#xff08;VRRM&#xff09;&#xff1a;600V 最大正向电压&…

C语言函数指针应用——计算器(转移表)的使用

对与上一节&#xff0c;我们对指针函数已经有了深刻意识了&#xff1b;练一练吧 如果还没有学习到&#xff0c;也是没有关系的&#xff0c;可以看一看这一篇 C语言详解指针-CSDN博客https://blog.csdn.net/Asuku_/article/details/137690083希望能提高你对指针的理解 计算器的实…

使用Riverpod在Flutter中创建Todo列表

使用Riverpod在Flutter中创建Todo列表 视频 https://youtu.be/mlbeSD1KSIo https://www.bilibili.com/video/BV1jj42197c8/ 前言 原文 https://ducafecat.com/blog/flutter-todo-list-with-riverpod-guide-02 学习如何使用Riverpod在Flutter中构建一个功能完整的Todo列表应用…