当前位置: 首页 > news >正文

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),而无需指定他们具体的类。

相关文章:

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

问题的提出 从前面我们已经使用了工厂方法模式 解决了一些问题。 现在 策划又提出了新的需求&#xff1a;对于各个怪物&#xff0c;在不同的场景下&#xff0c;怪物的面板数值会发生变化&#xff0c; //怪物分类&#xff1a;亡灵类&#xff0c;元素类&#xff0c;机械类 …...

第8周 Python面向对象编程刷题

单击题目&#xff0c;直接跳转到页面刷题&#xff0c;一周后公布答案。加入QQ群701657573&#xff0c;随时答疑交流。 218&#xff1a;类对象属性219&#xff1a;坐标对象相加220&#xff1a;计算周长221&#xff1a;学生分数总和222&#xff1a;车辆类中创建引擎类对象223&am…...

【学习心得】神经网络知识中的符号解释②

我在上篇文章中初步介绍了一些神经网络中的符号&#xff0c;只有统一符号及其对应的含义才能使我自己在后续的深度学习中有着一脉相承的体系。如果对我之前的文章感兴趣可以点击链接看看哦&#xff1a; 【学习心得】神经网络知识中的符号解释①http://t.csdnimg.cn/f6PeJ 一、…...

Igh related:Small Bug And Notes Record.

Write at the top My computer got some silly problem with the typing software that my Chinese IM does’t work again. So I’ll try to record the things happened in English. If any error,DM me plz. BUGs BUG1 Undefined symbol Identifier “CLOCK_MONOTONIC”…...

【QT入门】Qt自定义控件与样式设计之qss介绍(Qt style sheet)

往期回顾&#xff1a; 【QT入门】 无边框窗口设计之实现圆角窗口-CSDN博客【QT入门】 无边框窗口设计综合运用之自定义标题栏带圆角阴影的窗口-CSDN博客 【QT入门】 无边框窗口设计之综合运用&#xff0c;实现WPS的tab页面-CSDN博客 【QT入门】Qt自定义控件与样式设计之qss介绍…...

[ LeetCode ] 题刷刷(Python)-第49题:字母异位词分组

题目描述 给你一个字符串数组&#xff0c;请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。 字母异位词是由重新排列源单词的所有字母得到的一个新单词。 即将含有相同字符但排列顺序不同的字符串放入同一个组中。 示例 示例 1: 输入: strs ["eat", &qu…...

冒泡排序算法实现步骤

算法实现的过程&#xff1a; 1. 定义问题&#xff1a; - 算法是用来解决某一特定计算问题的方法步骤。例如&#xff0c;对于排序问题&#xff0c;我们需要一个算法对一组无序的整数进行排序。 2. 设计算法&#xff1a; - 冒泡排序是一种基础的排序算法。它的设计思路是…...

js实现webp转png/jpg

网上保存的图片是webp类型的&#xff0c;但是我把它嵌入flac格式的音频里后导致网页中无法播放 wps要会员&#xff0c;真麻烦。 完整代码&#xff1a; <!DOCTYPE html> <html lang"zh-CN"> <head> <meta charset"UTF-8">…...

DVWA -File Upload-通关教程-完结

DVWA -File Upload-通关教程-完结 文章目录 DVWA -File Upload-通关教程-完结页面功能LowMediumHighImpossible 页面功能 此页面的功能为选择某个图片文件点击Upload按钮上传&#xff0c;上传成功后得知文件上传路径为DVWA\hackable\uploads。 Low 源码审计 这段 PHP 代码…...

中介者模式:简化对象间通信的协调者

在面向对象的软件开发中&#xff0c;中介者模式是一种重要的行为型设计模式&#xff0c;用于降低多个对象间通信的复杂性。通过提供一个中心化的对象来处理不同组件之间的交互&#xff0c;中介者模式使得组件间不必显式引用彼此&#xff0c;从而使其松散耦合、更易于维护。本文…...

【Python系列】pydantic版本问题

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…...

深度学习-多尺度训练的介绍与应用

一、引言 在当今快速发展的人工智能领域&#xff0c;多尺度训练已经成为了一种至关重要的技术&#xff0c;特别是在处理具有复杂结构和不同尺度特征的数据时。这种技术在许多应用中发挥着关键作用&#xff0c;例如图像识别、自然语言处理和视频分析等。 多尺度训练的定义 多尺…...

详解单文件组件

当你创建 Vue 单文件组件时&#xff0c;通常会包含三个部分&#xff1a;<template>、<script> 和 <style>。这三个部分分别用于定义组件的模板、逻辑和样式。让我更详细地解释一下它们的作用和用法&#xff1a; <template> <template> 标签用于…...

MLeaksFinder报错

1.报错&#xff1a;FBClassStrongLayout.mm 文件&#xff1a;layoutCache[currentClass] ivars; 解决&#xff1a;替换为layoutCache[(id)currentClass] ivars; 2.编译正常但运行时出现crash indirect_symbol_bindings[i] cur->rebinding FBRetainCycleDetector iOS15 …...

【心路历程】初次参加蓝桥杯实况

送给大家一句话&#xff1a; 寂静的光辉平铺的一刻&#xff0c;地上的每一个坎坷都被映照得灿烂。 – 史铁生 《我与地坛》 初次参加蓝桥杯有感 一点小小的震撼难评的做题过程A题 艺术与篮球问题描述解题 B 题 五子棋问题描述解题 C题 训练士兵问题描述解题 D题 团建解题 E题 …...

微信小程序全屏开屏广告

效果图 代码 <template><view><!-- 自定义头部 --><u-navbar title" " :bgColor"bgColor"><view class"u-nav-slot" slot"left"><view class"leftCon"><view class"countDown…...

记录day1

1.早上 ①协同过滤算法 基于物品基于用户分别是如何实现的 相似度的计算方式 基于用户和基于物品的区别 实时性和新物品这里&#xff1a; 实时性指的是用户有新行为&#xff0c;这样基于物品就好&#xff0c;因为用户新行为了&#xff0c;用户矩阵不会变化&#xff0c;用户…...

stm32GPio的开发基础

上拉输入&#xff1a;高电平&#xff08;弱高电平&#xff0c;一般默认&#xff09; 下拉输入&#xff1a;低电平 没有上拉下拉就是处于一个不确定的状态 推挽wan输出&#xff1a;驱动能力比较强&#xff0c;推挽是因为往外推 set就是1&#xff0c;reset就是0 XMX就是封装的…...

DataSource

目录 1、 DataSource 1.1、 * 建立数据库连接的参数对象 1.1.1、 * 数据库url 1.1.2、 * 数据库用户名 1.1.3、 * 数据库密码 1.1.4、 * 数据库驱动名称 <...

Linux防止暴力破解密码脚本

1.认识记录linux记录安全的日志 [roottestpm ~]# cd /var/log/ [roottestpm log]# ls | grep secure secure 2.该日志的内容查看 [roottestpm log]# tail -f secure #表示ssh身份验证失败 Aug 29 23:35:03 testpm sshd[111245]: pam_unix(sshd:auth): authentication fa…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

conda相比python好处

Conda 作为 Python 的环境和包管理工具&#xff0c;相比原生 Python 生态&#xff08;如 pip 虚拟环境&#xff09;有许多独特优势&#xff0c;尤其在多项目管理、依赖处理和跨平台兼容性等方面表现更优。以下是 Conda 的核心好处&#xff1a; 一、一站式环境管理&#xff1a…...

vscode里如何用git

打开vs终端执行如下&#xff1a; 1 初始化 Git 仓库&#xff08;如果尚未初始化&#xff09; git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

高等数学(下)题型笔记(八)空间解析几何与向量代数

目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

MySQL:分区的基本使用

目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区&#xff08;Partitioning&#xff09;是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分&#xff08;分区&#xff09;可以独立存储、管理和优化&#xff0c;…...

手机平板能效生态设计指令EU 2023/1670标准解读

手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读&#xff0c;综合法规核心要求、最新修正及企业合规要点&#xff1a; 一、法规背景与目标 生效与强制时间 发布于2023年8月31日&#xff08;OJ公报&…...

高考志愿填报管理系统---开发介绍

高考志愿填报管理系统是一款专为教育机构、学校和教师设计的学生信息管理和志愿填报辅助平台。系统基于Django框架开发&#xff0c;采用现代化的Web技术&#xff0c;为教育工作者提供高效、安全、便捷的学生管理解决方案。 ## &#x1f4cb; 系统概述 ### &#x1f3af; 系统定…...

leetcode_69.x的平方根

题目如下 &#xff1a; 看到题 &#xff0c;我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历&#xff0c;我们是整数的平方根&#xff0c;所以我们分两…...