C++ 设计模式——工厂方法模式

工厂方法模式

      • 工厂方法模式
        • 主要组成部分
        • 代码实现
        • 工厂方法模式模式的 UML 图
        • 工厂方法模式 UML 图解析
        • 优点和缺点
        • 适用场景

工厂方法模式

工厂方法模式是一种创建型设计模式,它通过定义一个接口用于创建对象,但由子类决定实例化哪个类。与简单工厂模式不同,工厂方法模式将对象的创建委托给子类,从而实现更好的扩展性和灵活性。

引入“工厂方法模式(实现意图):定义一个用于创建对象的接口,但由子类决定要实例化的类是哪一个。该模式使得某个类的实例化延迟到子类。

主要组成部分
  • 产品接口(Product):定义了工厂方法所创建的对象的接口。
  • 具体产品(ConcreteProduct):实现了产品接口的具体类。
  • 工厂接口(Creator):声明了工厂方法,返回一个产品对象。
  • 具体工厂(ConcreteCreator):实现了工厂接口,返回具体产品的实例。
代码实现

以下代码,主要用工厂方法模式创建不同类型的怪物对象:

#include <iostream>
#include <string>

using namespace std;

// 怪物父类
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;  // 攻击力
};

// 亡灵类怪物
class M_Undead : public Monster
{
public:
    M_Undead(int life, int magic, int attack) : Monster(life, magic, attack)
    {
        cout << "一只亡灵类怪物来到了这个世界" << endl;
    }
    // 其他代码略....
};

// 元素类怪物
class M_Element : public Monster
{
public:
    M_Element(int life, int magic, int attack) : Monster(life, magic, attack)
    {
        cout << "一只元素类怪物来到了这个世界" << endl;
    }
    // 其他代码略....
};

// 机械类怪物
class M_Mechanic : public Monster
{
public:
    M_Mechanic(int life, int magic, int attack) : Monster(life, magic, attack)
    {
        cout << "一只机械类怪物来到了这个世界" << endl;
    }
    // 其他代码略....
};

// 工厂方法模式
// 所有工厂类的父类
class M_ParFactory
{
public:
    virtual Monster* createMonster() = 0; // 纯虚函数
    virtual ~M_ParFactory() {} // 虚析构函数
};

// 亡灵类怪物工厂
class M_UndeadFactory : public M_ParFactory
{
public:
    virtual Monster* createMonster()
    {
        return new M_Undead(300, 50, 80); // 创建亡灵类怪物
    }
};

// 元素类怪物工厂
class M_ElementFactory : public M_ParFactory
{
public:
    virtual Monster* createMonster()
    {
        return new M_Element(200, 80, 100); // 创建元素类怪物
    }
};

// 机械类怪物工厂
class M_MechanicFactory : public M_ParFactory
{
public:
    virtual Monster* createMonster()
    {
        return new M_Mechanic(400, 0, 110); // 创建机械类怪物
    }
};

// 全局创建怪物对象的函数
Monster* Gbl_CreateMonster(M_ParFactory* factory)
{
    return factory->createMonster(); // 根据工厂创建怪物
}

// 创建怪物工厂子类模板
template <typename T>
class M_ChildFactory : public M_ParFactory
{
public:
    virtual Monster* createMonster() {
        return new T(300, 50, 80); // 创建具体类型的怪物
    }
};

// 使用示例
int main()
{
    // 使用具体工厂创建怪物
    M_ParFactory* undeadFactory = new M_UndeadFactory();
    Monster* undead = Gbl_CreateMonster(undeadFactory);
    delete undead; // 释放内存
    delete undeadFactory;

    M_ParFactory* elementFactory = new M_ElementFactory();
    Monster* element = Gbl_CreateMonster(elementFactory);
    delete element; // 释放内存
    delete elementFactory;

    M_ParFactory* mechanicFactory = new M_MechanicFactory();
    Monster* mechanic = Gbl_CreateMonster(mechanicFactory);
    delete mechanic; // 释放内存
    delete mechanicFactory;

    // 使用模板工厂创建怪物
    M_ChildFactory<M_Undead> undeadChildFactory;
    Monster* undeadChild = Gbl_CreateMonster(&undeadChildFactory);
    delete undeadChild; // 释放内存

    return 0;
}

工厂方法模式模式的 UML 图

工厂方法模式模式的 UML 图

工厂方法模式 UML 图解析
  • 类关系
    • Monster:抽象基类,定义了怪物的基本属性(如 m_lifem_magicm_attack)。
    • M_UndeadM_ElementM_Mechanic:具体类,继承自 Monster,实现不同类型的怪物。
  • 工厂类
    • M_ParFactory:抽象工厂类,定义了创建怪物的接口 createMonster
    • M_UndeadFactoryM_ElementFactoryM_MechanicFactory:具体工厂类,继承自 M_ParFactory,分别负责创建不同类型的怪物。
    • M_ChildFactory:模板工厂类,能够创建任意类型的怪物,提供更灵活的创建方式。
  • 稳定部分
    • Gbl_CreateMonster 函数依赖的 Monster 类和 M_ParFactory 类属于稳定部分,不需要更改。
  • 变化部分
    • M_UndeadFactoryM_ElementFactoryM_MechanicFactory 类以及具体怪物类(如 M_UndeadM_Mechanic)属于变化部分。Gbl_CreateMonster 函数不依赖于这些变化部分。
  • 扩展新类型
    • 当需要引入新怪物类型(例如 M_Beast)时,无需更改 Gbl_CreateMonster 函数或修改 MonsterFactorycreateMonster 方法。只需创建一个继承自 Monster 的新类 M_Beast 和一个继承自 M_ParFactory 的新工厂类 M_BeastFactory,这符合开闭原则:对扩展开放,对修改关闭。
  • 隐藏实现细节
    • 如果 M_ParFactory 及其子类由第三方开发,工厂方法模式可以有效隐藏具体怪物类(如 M_UndeadM_ElementM_Mechanic),避免暴露给开发者。
  • 接口扩展
    • M_ParFactory 的接口可以根据需要扩展,例如增加对 NPC(非玩家角色,如商人、路人等)的创建支持,或为 createMonster 提供默认实现。
  • 增加工厂类的代价
    • 增加新的工厂类是工厂方法模式的必然代价,但这为系统的灵活性和可扩展性提供了保障。
优点和缺点
  • 优点
    • 符合开闭原则:新增产品时,只需创建新的产品类和相应的工厂类,无需修改现有代码。
    • 减少耦合:客户端代码与具体产品类解耦,依赖于抽象工厂接口,增强了系统的灵活性。
    • 扩展性强:可以方便地扩展新的产品类型,适合复杂系统的需求变化。
    • 提高代码可读性:通过明确的工厂类和产品类的分离,代码结构更加清晰。
  • 缺点
    • 类的数量增加:每新增一种产品都需要创建相应的工厂类,可能导致类的数量剧增,增加系统复杂性。
    • 实现复杂性:对于简单产品的创建,工厂方法模式可能显得过于复杂,增加不必要的开销。
    • 难以管理:如果产品种类过多,可能导致工厂类的管理变得困难。
适用场景
  • 产品族:需要创建一系列相关或相互依赖的对象时,工厂方法模式非常适合。
  • 产品类型变化频繁:当产品类型经常变化,且需要动态地扩展新产品时,工厂方法模式提供了良好的灵活性。
  • 需要解耦的系统:当系统需要将对象创建与使用分离时,工厂方法模式可以有效降低耦合度。
  • 复杂对象的创建:当对象的创建过程复杂,且可能涉及多个步骤时,工厂方法模式可以封装这些复杂性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

数据结构----栈

一丶概念 只能在一端进行插入和删除操作的线性表&#xff08;又称为堆栈&#xff09;&#xff0c;进行插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底 二丶特点 先进后出 FILO first in last out 后进先出 LIFO last in first out 三丶顺序栈 逻辑结构&…

什么是制造业项目管理软件?适合制造企业的项目管理软件具备哪些特征

当前&#xff0c;我国的制造业呈现出稳步增长与风险并存的现象。经济构建以国内大循环为主体&#xff0c;国产替代的浪潮正在席卷国内制造业&#xff0c;越来越多的制造领域企业开始启动数字化变革来支撑企业的迅猛发展&#xff0c;进一步优化项目管理流程&#xff0c;促进研发…

Impala 与 Hive 的比较

Impala 与 Hive 的关系 impala是基于hive的大数据分析查询引擎&#xff0c;直接使用hive的元数据库metadata&#xff0c;意味着impala元数据都存储在hive的metastore当中&#xff0c;并且impala兼容hive的绝大多数sql语法。所以需要安装impala的话&#xff0c;必须先安装hive&…

开发小运维-常用Linux资源监控命令

文章目录 简介常用命令/proc/meminfo&#xff08;内存&#xff09;free&#xff08;内存信息&#xff09;top&#xff08;进程动态&#xff09;df &#xff08;磁盘信息&#xff09;du&#xff08;磁盘信息&#xff09;ps&#xff08;进程状态&#xff09;vmstat&#xff08;内…

iOS的App启动详细过程(底层知识)

1.虚拟内存 & ASLR 在早期计算机中数据是直接通过物理地址访问的&#xff0c;这就造成了下面两个问题 1.内存不够用 2.数据安全问题 内存不够 ---> 虚拟内存 虚拟内存就是通过创建一张物理地址和虚拟地址的映射表来管理内存&#xff0c;提高了CPU利用率&#xff0c;…

IDEA:如何在idea中设置自动导包

这里使用的是idea2020版本,但是不同版本操作不会有较大的差别. 在Editer中展开General之后,选中Auto Import,最后勾选中Add unambiguous imports on the fly.

DMHS数据同步工具

DMHS数据同步工具 ​ 本章节主要介绍DM数据同步工具DMHS的使用&#xff0c;通过将oracle11g的数据同步到DM8的过程来理解DMHS的功能和作用。 安装前的准备 端口、服务信息 IP地址服务名称版本端口安装路径192.168.19.136OracleOracle11.0.21521/opt/oracle/DMHS源端dmhs_V3…

深入理解Faiss:高效向量检索的利器

近年来&#xff0c;随着人工智能和机器学习技术的飞速发展&#xff0c;向量检索技术变得越来越重要。无论是在推荐系统、图像搜索还是自然语言处理等领域&#xff0c;向量检索都扮演着至关重要的角色。而在众多向量检索库中&#xff0c;Faiss&#xff08;Facebook AI Similarit…

基于Springboot 和Vue 的高校宿舍管理系统源码

网络上很多宿舍管理系统都不完整&#xff0c;大多数缺少数据库文件&#xff0c;所在使用极其不方便&#xff0c;由于本人程序员&#xff0c;根据代码&#xff0c;自己花时间不全了数据库文件&#xff0c;并且可以完美运行&#xff01;&#xff01;&#xff01;&#xff01;&…

C++:C/C++的内存管理

目录 C/C内存分布 C语言中动态内存管理方式 C内存管理方式 new/delete操作内置类型 new/delete操作自定义类型 operator new与operator delete函数 new和delete的实现原理 定位new表达式 常见问题 malloc/free和new/delete的区别 内存泄漏 C/C内存分布 我们先来看以…

【傅里叶分析】复数基础知识

【傅里叶分析】复数基础知识 复数复数的几何意义与点的对应与向量的对应 复数与极坐标辐角与辐角主值三角函数 参考文献 本文参考了网上的其他文章&#xff0c;已在文末参考文献中列出&#xff1b;如有侵权&#xff0c;请联系我删除。 复变函数是傅里叶分析的基础&#xff0c;而…

【原创公式】【完全二叉树】叶结点的计算【数据结构】

完全二叉树叶结点的计算 【铺垫】1叶结点即度为0的结点 2完全二叉树中度为1的结点只可能有0或1个 3完全二叉树的设叶结点仅可能出现在最后2层 设有完全二叉树T 【区分】第k层有a个叶结点≠第k层有a个结点 &#xff08;1&#xff09;第k层有a个叶结点&#xff1a;T的形态不唯一&…

【Linux操作系统】进程控制

目录 一、进程创建1.1 认识fork1.2 写时拷贝 二、进程终止2.1 进程退出2.2 函数退出2.3 exit 三、进程等待四、程序替换 一、进程创建 1.1 认识fork fork函数是系统调用接口&#xff0c;用来创建子进程的 根据进程的pid&#xff0c;可以看出父进程fork后分为父进程和子进程…

单片机原理及技术(六)—— 中断系统的工作原理

目录 一、AT89S51中断技术概述 二、AT89S51中断系统结构 2.1 中断请求源 2.2 中断请求标志寄存器 2.2.1 TCON 寄存器 2.2.2 SCON 寄存器 三、中断允许与中断优先级的控制 3.1 中断允许寄存器 IE 3.2 中断优先级寄存器 IP 四、响应中断请求的条件 五、外部中断的触发…

深入理解java web分层架构的高内聚低耦合

​ 在软件开发中&#xff0c;构建一个高效、可维护且可扩展的应用系统一直是开发者追求的目标。分层架构和依赖注入&#xff08;IOC&#xff09;是实现这一目标的重要策略。本文将深入探讨三层架构的高内聚特性、低耦合的设计原则&#xff0c;以及如何通过IOC&#xff08;控制反…

FPGA开发——在线调试工具Signal Tap的使用

一、简介 在我们进行FPGA进行开发时通常都会经历代码编写&#xff0c;仿真&#xff0c;下板验证等过程。使用FPGA进行开发的小伙伴都知道&#xff0c;在代码编写时往往花费不了太长的时间&#xff0c;下板验证更是。在开发中占绝大部分时间的是仿真&#xff0c;有时候编写代码只…

基于Python的火车票售票系统/基于django的火车购票系统

摘 要 随着信息技术和网络技术的飞速发展&#xff0c;人类已进入全新信息化时代&#xff0c;传统管理技术已无法高效&#xff0c;便捷地管理信息。为了迎合时代需求&#xff0c;优化管理效率&#xff0c;各种各样的管理系统应运而生&#xff0c;各行各业相继进入信息管理时代&…

Ubuntu虚拟机服务器的搭建

01.VMware安装 略。 02.Ubuntu虚拟机安装 略。 03.配置Ubuntu虚拟机网络 参考视频&#xff1a; Ubutu虚拟机网络配置&#xff08;桥接&#xff09;https://www.bilibili.com/video/BV1bG411V72A/?spm_id_from333.999.0.0&vd_sourced1fd4bcc46805ab35cc8bbb5a8bf318f…

解决springboot中Aspect注解不生效问题

如下图所示&#xff0c;配置了一个注解类型的Aspect&#xff0c;结果一直不生效 运行结果可以看到&#xff0c;其他非注解类型的Aspect都顺利执行了&#xff0c;但是这个注解的切面就是没有执行 当时也在网上搜了半天&#xff0c;包括在启动类增加配置&#xff0c;接口都要加上…

HTTPS通讯全过程

HTTPS通讯全过程 不得不说&#xff0c;https比http通讯更加复杂惹。在第一次接触https代码的时候&#xff0c;不知道为什么要用用证书&#xff0c;公钥是什么&#xff1f;私钥是什么&#xff1f;他们作用是什么&#xff1f;非对称加密和对称加密是啥&#xff1f;天&#xff0c;…