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

问题的提出

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

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

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

那么就有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.mzph.cn/news/814305.shtml

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

相关文章

MATLAB 自定义实现点云法向量和曲率计算(详细解读)(64)

MATLAB 自定义实现点云法向量和曲率计算(详细解读)(64) 一、算法介绍二、算法步骤三、算法实现1.代码 (完整,注释清晰,可直接用)2.结果一、算法介绍 首先说明: ------这里代码手动实现,不调用matlab提供的法向量计算接口,更有助于大家了解法向量和曲率的计算方法,…

docker部署Prometheus+AlertManager实现邮件告警

文章目录 一、环境准备1、硬件准备&#xff08;虚拟机&#xff09;2、关闭防火墙&#xff0c;selinux3、所有主机安装docker 二、配置Prometheus1、docker启动Prometheus 三、添加监控节点1、docker启动node-exporter 四、Prometheus配置node-exporter1、修改prometheus.yml配置…

【网站项目】摄影竞赛小程序

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

刷题之动态规划-回文串

前言 大家好&#xff0c;我是jiantaoyab&#xff0c;开始刷动态规划的回文串类型相关的题目 动态规划5个步骤 状态表示 &#xff1a;dp数组中每一个下标对应值的含义是什么>dp[i]表示什么状态转移方程&#xff1a; dp[i] 等于什么1 和 2 是动态规划的核心步骤&#xff0c;…

某次众测的加解密对抗

前言 起源于某次众测中&#xff0c;遇到请求包响应包全密文的情况&#xff0c;最终实现burp中加解密。 用到的工具有 sekiro&#xff08;rpc转发&#xff09;flask&#xff08;autodecoder自定义接口&#xff09;autodecoder&#xff08;burp插件转发&#xff09; debug部分…

ClickHouse--18--argMin() 和argMax()函数

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 argMin() 和argMax()函数业务场景使用案例1.准备表和数据&#xff1a;业务场景一&#xff1a;查看salary 最高和最小的user业务场景二&#xff1a;根据更新时间获取…

【fastapi】搭建第一个fastapi后端项目

本篇文章介绍一下fastapi后端项目的搭建。其实没有什么好说的&#xff0c;按照官方教程来即可&#xff1a;https://fastapi.tiangolo.com/zh/ 安装依赖 这也是我觉得python项目的槽点之一。所有依赖都安装在本地&#xff0c;一旦在别人电脑上编写项目就又要安装一遍。很扯淡。…

最优算法100例之45-不用循环乘法求1-n的和

专栏主页&#xff1a;计算机专业基础知识总结&#xff08;适用于期末复习考研刷题求职面试&#xff09;系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 要求不能使用乘除法、for、while、if、else、switch、case等关键字及条件判断语句。不能用循…

【opencv】示例-neural_network.cpp 使用机器学习模块创建并训练一个简单的多层感知机(神经网络)模型...

#include <opencv2/ml/ml.hpp> // 引入OpenCV的机器学习模块using namespace std; // 使用标准命名空间 using namespace cv; // 使用OpenCV命名空间 using namespace cv::ml; // 使用OpenCV机器学习命名空间int main() {//创建随机训练数据Mat_<float> data(100, …

字符和字符串操作函数总结

索引 一 . 字符操作函数1. 字符分类函数2. 字符转换函数 二 . 字符串操作函数长度不受限制的字符串操作函数1. strcpy函数的使用和模拟实现2. strcat函数的使用和模拟实现3. strcmp函数的使用和模拟实现 长度受限制的字符串操作函数1. strncpy函数的使用2. strncat函数的使用3.…

RT-Thread 启动流程源码详解

RT-Thread 启动流程 一般了解一份代码大多从启动部分开始,同样这里也采用这种方式,先寻找启动的源头。RT-Thread 支持多种平台和多种编译器,而 rtthread_startup() 函数是 RT-Thread 规定的统一启动入口。一般执行顺 序是:系统先从启动文件开始运行,然后进入 RT-Thread 的…

vi编辑器

目录 一、文本编辑器vi命令 1.作用&#xff1a; 2.vi和vim 二、vi编辑器的三种模式 三、输入模式 四、命令模式 五、末行模式 一、文本编辑器vi命令 1.作用&#xff1a; 创建或修改文本文件 维护Linux系统中的各种配置文件 2.vi和vim vi:类UNIX操作系统的默认文本编辑器…

标准更新丨美国发布玩具安全标准ASTM F963-23

2023年10月13日&#xff0c;美国材料试验协会 (ASTM)发布了玩具安全标准ASTM F963-23。新版标准主要修订了声响、电池可触及性、膨胀材料和弹射玩具的技术要求&#xff0c;另外&#xff0c;澄清和调整了邻苯二甲酸酯、玩具基材重金属的豁免以及溯源标签的要求&#xff0c;使其保…

基于Python的豆瓣电影、豆瓣电影评分可视化、豆瓣电影评分预测系统

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

从零开始写一个RTSP服务器(一)RTSP协议讲解

目录 前言一、什么是RTSP协议&#xff1f;二、RTSP协议详解2.1 RTSP数据格式2.2 RTSP请求的常用方法2.3 RTSP交互过程2.4 sdp格式 三、RTP协议3.1 RTP包格式3.2 RTP OVER TCP 四、RTCP 前言 为什么要写这个系列&#xff1f; 因为我自己在学习rtsp协议想自己从零写一个rtsp服务…

【opencv】示例-npr_demo.cpp 非真实感渲染:边缘保留平滑、细节增强、铅笔素描/彩色铅笔绘图和风格化处理...

Edge Preserve Smoothing- Using Normalized convolution Filter Edge Preserve Smoothing-Using Recursive Filter Detail Enhancement Pencil sketch/Color Pencil Drawing Stylization /* * npr_demo.cpp * * 作者: * Siddharth Kherada <siddharthkherada27[at]gmail[do…

JavaScript代码挑战

让我们回到朱莉娅和凯特关于狗的研究。这次&#xff0c;他们想把狗的年龄转换成人的年龄&#xff0c;并计算出研究中狗的平均年龄。 创建一个函数 “calcAverageHumanAge”&#xff0c;该函数接受一个狗的年龄数组&#xff08;‘age’&#xff09;&#xff0c;并按顺序执行以下…

KDTree索引(K近邻搜索,半径R内近邻搜索)——PCL

K近邻搜索&#xff08;K Nearest Neighbors&#xff09; K近邻搜索是一种基于点数量的搜索方法&#xff0c;它会找到指定点附近最接近的K个邻居点。K近邻搜索中的K值是一个参数&#xff0c;您需要指定要搜索的邻居数量。该方法适用于需要查找固定数量邻居点的情况&#xff0c;…

Redis队列与Stream

Redis队列与Stream、Redis 6多线程详解 Redis队列与StreamStream总述常用操作命令生产端消费端单消费者消费组消息消费 Redis队列几种实现的总结基于List的 LPUSHBRPOP 的实现基于Sorted-Set的实现PUB/SUB&#xff0c;订阅/发布模式基于Stream类型的实现与Java的集成消息队列问…

Django模型入门

Django模型入门 为了能够学会使用Django模型&#xff0c;本节通过构建一个实际的Django模型来帮助读者尽快入门。 3.2.1 定义模型 既然Django模型实现了ORM功能&#xff0c;那么它就是对数据库实例的描述和实现。下面&#xff0c;我们通过一个简单的实例进行讲解。 如果需…