C++11 设计模式3. 工厂方法模式

简单工厂模式的遗留问题

    //从上面的代码可以看到,简单工厂模式确实实现了new 出来具体对象, 和 业务逻辑的分离,
    //但是不符合 "开闭原则"
    //"开闭原则"说的是代码扩展性问题——对扩展开放,对修改关闭(封闭);
    //假设过了两天,策划找到我们说:加一种怪物,新怪物类型:M_Beast(野兽类)
    //那我们要怎么改呢?首先肯定是加一个 M_Beast类了,继承Monster
    //然后MonsterFactory 中改动 createMonster方法完成。
    //很显然,我们要改动到原先的 createMonster 方法,这是违反了 "开闭原则的"。
    //那么如何改动才合理呢?这就要用到 "工厂方法" 模式

解决方案:工厂方法 模式

工厂方法(Factory Method)模式:简称工厂模式或者多态工厂模式。
    //与简单工厂模式比,灵活性更强,实现也更加复杂,引入更多的新类。
    //M_UndeadFactory,M_ElementFactory,M_MechanicFactory类,有一个共同的父类M_ParFactory(工厂抽象类):
      //符合开闭原则,付出的代价是需要新增加多个新的工厂类。
    //定义(实现意图):定义一个用于创建对象的接口(M_ParFactory类中的createMonster成员函数,这其实就是个工厂方法,工厂方法模式的名字也是由此而来),
      //但由子类(M_UndeadFactory、M_ElementFactory、M_MechanicFactory)决定要实例化的类是哪一个。
      //该模式使得某个类(M_Undead、M_Element、M_Mechanic)的实例化延迟到子类(M_UndeadFactory、M_ElementFactory、M_MechanicFactory)。
    //出现新怪物类型:M_Beast(野兽类)。
    //一般可以认为,将简单工厂模式的代码经过把工厂类进行抽象改造成符合开闭原则后的代码,就变成了工厂方法模式的代码。
    

代码实现

#include <iostream>
using namespace std;//(1)简单工厂(Simple Factory)模式
//策划:亡灵类怪物,元素类怪物,机械类怪物:都有生命值,魔法值,攻击力三个属性。
//Monster作为父类,M_Undead(亡灵类),M_Element(元素类怪物),M_Mechanic(机械类怪物)。namespace _namespace1 {class Monster {public:Monster(int life, int magic, int attack) : m_life(life), m_magic(magic), m_attack(attack){};virtual ~Monster() {};protected:int m_life;int m_magic;int m_attack;};//M_Undead(亡灵类)class M_Undead :public Monster {public:M_Undead(int life, int magic, int attack) :Monster(life, magic, attack) {cout << "创建了一个亡灵类 life = " << m_life << "  magic = " << m_magic << "  attack = " << m_attack << endl;}};//M_Element(元素类怪物)class M_Element :public Monster {public:M_Element(int life, int magic, int attack) :Monster(life, magic, attack) {cout << "创建了一个元素类怪物 life = " << m_life << "  magic = " << m_magic << "  attack = " << m_attack << endl;}};//M_Mechanic(机械类怪物)class M_Mechanic :public Monster {public:M_Mechanic(int life, int magic, int attack) :Monster(life, magic, attack) {cout << "创建了一个机械类怪物 life = " << m_life << "  magic = " << m_magic << "  attack = " << m_attack << endl;}};//所有工厂类的父类class M_ParFactory{public:virtual Monster* createMonster() = 0; //具体的实现在子类中进行virtual ~M_ParFactory() {} //做父类时析构函数应该为虚函数};//每一个具体的类都有自己的工厂class Undead_Factory :public M_ParFactory {public:Monster* createMonster() {return new M_Undead(111, 222, 333);}};class Element_Factory :public M_ParFactory {public:Monster* createMonster() {return new M_Element(444, 555, 666);}};class Mechanic_Factory :public M_ParFactory {public:Monster* createMonster() {return new M_Mechanic(777, 888, 999);}};//这里要有一个方法能够返回需要的具体的Monster,参数为M_ParFactory类型指针Monster * g_createMonster_use_factory_method(M_ParFactory * parfactory) {return parfactory->createMonster();}};void testfactorymethod() {_namespace1::M_ParFactory *par1 = new _namespace1::Undead_Factory();_namespace1::Monster *pmon1 = _namespace1::g_createMonster_use_factory_method(par1);_namespace1::M_ParFactory *par2 = new _namespace1::Element_Factory();_namespace1::Monster *pmon2 = _namespace1::g_createMonster_use_factory_method(par2);_namespace1::M_ParFactory *par3 = new _namespace1::Mechanic_Factory();_namespace1::Monster *pmon3 = _namespace1::g_createMonster_use_factory_method(par3);delete par1;delete par2;delete par3;delete pmon1;delete pmon2;delete pmon3;}int main()
{_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口//"工厂方法" 模式testfactorymethod();std::cout << "Hello World!\n";
}

简单工厂模式 和 工厂方法模式 对比


    //简单工厂模式把创建对象这件事放到了一个统一的地方来处理,弹性比较差。而工厂方法模式相当于建立了一个程序实现框架,从而让子类来决定对象如何创建。
    //工厂方法模式往往需要创建一个与产品等级结构(层次)相同的工厂等级结构,这也增加了新类的层次结构和数目。

使用模版

//全局的用于创建怪物对象的函数,注意形参的类型是工厂父类类型的指针,返回类型是怪物父类类型的指针Monster* Gbl_CreateMonster(M_ParFactory* factory,int canshu1,int canshu2,int canshu3){return  factory->createMonster1(canshu1, canshu2, canshu3); //createMonster虚函数扮演了多态new的行为,factory指向的具体怪物工厂类不同,创建的怪物对象也不同。}//-------------------//不想创建太多工厂类,又想封装变化//创建怪物工厂子类模板template <typename T>class M_ChildFactory :public M_ParFactory{public:virtual Monster* createMonster1(int canshu1, int canshu2, int canshu3){return new T(canshu1, canshu2, canshu3); //如果需要不同的值则可以通过createMonster的形参将值传递进来}};

工厂方法模式的UML图

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

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

相关文章

如何在OceanBase v4.2 中快速生成随机数据

在使用传统数据库如 MySQL 和 Oracle 时&#xff0c;由于缺乏多样化的随机数据生成方案&#xff0c;或者实现成本过高&#xff0c;构造随机数据的开发成本受到了影响。OceanBase在老版本中虽然有相应的解决方案&#xff0c;但语法复杂和性能较差等问题仍然存在。 现在&#xf…

【漏洞复现】润乾报表平台 InputServlet接口处存在任意文件上传漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

车内AR互动娱乐解决方案,打造沉浸式智能座舱体验

美摄科技凭借其卓越的创新能力&#xff0c;为企业带来了革命性的车内AR互动娱乐解决方案。该方案凭借自研的AI检测和渲染引擎&#xff0c;打造出逼真的数字形象&#xff0c;不仅丰富了车机娱乐内容&#xff0c;更提升了乘客与车辆的互动体验&#xff0c;让每一次出行都成为一场…

C语言 循环控制——while和do-while语句

目录 whiel语句 do-while语句 while与do-while的区别 计数控制的循环 ​编辑标记控制的循环 whiel语句 do-while语句 while与do-while的区别 计数控制的循环 标记控制的循环

怎么构建临床知识图谱?

怎么构建临床知识图谱? 构建临床知识图谱传统临床指南的局限性决策的不确定性和个体差异构建真实临床知识图谱构建真实世界的临床事件图谱基于书本抽取的知识来自哪些书本&#xff1f;如何保证这些知识是最新的知识&#xff1f;如何不断融入最新的医学研究进展&#xff0c;从而…

挖掘未来:私有LTE/5G网络驱动智慧矿山的自动化

私有LTE/5G网络为世界上一些最偏远的角落提供无线连接。如果没有无线通信网络&#xff0c;各行业就无法满足增加产量、降低运营成本和减少环境破坏的需求。 在本案例研究中&#xff0c;我们着眼于自动化如何改变无线网络的动态。智慧矿山要求运营商无缝集成多个系统和应用程序…

探索Web3的奇迹:数字时代的新前景

在数字化时代的潮流中&#xff0c;我们不可避免地迎来了一个全新的篇章——Web3时代的到来。在这个时代中&#xff0c;区块链技术作为数字化世界的核心&#xff0c;正在重塑着我们的生活方式、经济模式以及社会结构。在Web3时代&#xff0c;我们将目睹着一个以去中心化、透明化…

32.WEB渗透测试-数据传输与加解密(6)

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;31.WEB渗透测试-数据传输与加解密&#xff08;5&#xff09; 关于discuz3.5的源码内容和…

小型社区与园区如何选购合适的停车场道闸系统?需注意什么

小型社区和园区停车场通常面临着空间有限、预算有限以及车流量相对较小的挑战。这些特点要求停车场的管理系统既要经济实用&#xff0c;又要能够满足基本的车辆管理需求&#xff0c;如安全性、通行效率和便捷性。针对这些特点&#xff0c;选择合适的停车道闸系统成为提高管理效…

天诚物联网锁亮相福州南京沈阳西安展会,与您见证AIoT行业发展

目光灼灼&#xff0c;步履不辍。自4月1日第七届CCLE中国教育后勤展览会一别&#xff0c;全场景AIoT解决方案服务商——江苏新巢天诚智能技术有限公司&#xff08;以下简称“天诚”&#xff09;打造的校园物联网锁软硬一体化解决方案获得了诸多准意向代理商、集成商同仁们的咨询…

2011年认证杯SPSSPRO杯数学建模B题(第二阶段)生物多样性的评估全过程文档及程序

2011年认证杯SPSSPRO杯数学建模 B题 生物多样性的评估 原题再现&#xff1a; 2010 年是联合国大会确定的国际生物多样性年。保护地球上的生物多样性已经越来越被人类社会所关注&#xff0c;相关的大规模科研和考察计划也层出不穷。为了更好地建立国际交流与专家间的合作&…

【网络安全】网络安全,你我同行——网络安全指南请查收~

网络是一把双刃剑&#xff0c;在给我们带来便捷生活的同时&#xff0c;也埋下了种种安全隐患。作为网络的亲身参与者&#xff0c;我们应该主动学习网络安全知识。快让我们一起来看看&#xff0c;本期安全小讲堂带来了哪些网络安全知识吧~ 01 常见网络安全隐患 网络安全问题无…

Docker镜像,什么是Docker镜像,Docker基本常用命令

docker镜像 1.1什么是镜像&#xff0c;镜像基础 1.1.1 镜像的简介 镜像是一种轻量级&#xff0c;可执行的独立软件包&#xff0c;也可以说是一个精简的操作系统。镜像中包含应用软件及应用软件的运行环境&#xff0c;具体来说镜像包含运行某个软件所需的所有内容&#xff0c;…

记一次逻辑漏洞拿下目标站点

开局某平台登录框 可做尝试手法 1、弱口令 2、万能密码 3、复杂密码逻辑绕过 4、登录框逻辑绕过 5、登录框注入 正文 某通用平台&#xff0c;系xxx科技公司开发全套模板通用系统&#xff0c;演示站踩点弱口令&#xff0c;这里主要梳理踩点思路 1、某接口未授权访问读系统用户…

前端Vue自定义勾选协议组件的开发与应用

摘要&#xff1a; 随着前端技术的不断发展&#xff0c;用户体验成为了软件开发中的关键要素。在登录、注册等场景中&#xff0c;勾选协议是常见的需求。本文旨在介绍一款基于 Vue.js 的自定义勾选协议组件的开发与应用&#xff0c;该组件适用于多种场景&#xff0c;并且具备良…

无代理备份ESXi虚拟机

目前&#xff0c;虚拟机主要采用映像级备份方式&#xff0c;因为这样才能保证虚拟机数据的完整性&#xff0c;尤其是对于像VMware ESXi这样的一类虚拟机管理程序上的虚拟机。除此之外&#xff0c;还有一种文件级备份方法&#xff0c;允许颗粒备份和还原。我们区分这两种备份方法…

基于springboot实现课程答疑管理系统项目【项目源码+论文说明】

基于springboot实现课程答疑管理系统演示 摘要 随着信息互联网信息的飞速发展&#xff0c;无纸化作业变成了一种趋势&#xff0c;针对这个问题开发一个专门适应师生交流形式的网站。本文介绍了课程答疑系统的开发全过程。通过分析企业对于课程答疑系统的需求&#xff0c;创建了…

vue控制台报错Duplicate keys detected: ‘xxxxx‘. This may cause an update error.解决方案

截图报错&#xff1a; 错误分析&#xff1a; 1、提示 Duplicate keys detected &#xff0c;翻译为&#xff1a;检测到重复的密钥 2、检查 v-for 代码&#xff0c;具体如下&#xff1a; 发现问题&#xff1a;v-for中的key是一个相同的值 解决问题 因此处使用的是测试数据&…

论如何在小程序展示超链接在线网页

在工作中遇到一个需求&#xff0c;就是在小程序中展示超链接网页&#xff0c;起初我是直接使用web-view标签 <web-view src"https://www.baidu.com/"/>但是web-view只能在开发阶段手机上展示&#xff0c;一旦小程序发布线上&#xff0c;就会出现下面这种情况“…

Spectre漏洞 v2 版本再现,影响英特尔 CPU + Linux 组合设备

近日&#xff0c;网络安全研究人员披露了针对英特尔系统上 Linux 内核的首个原生 Spectre v2 漏洞&#xff0c;该漏洞是2018 年曝出的严重处理器“幽灵”&#xff08;Spectre&#xff09;漏洞 v2 衍生版本&#xff0c;利用该漏洞可以从内存中读取敏感数据&#xff0c;主要影响英…