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

news2024/9/21 2:48:52

工厂方法模式

      • 工厂方法模式
        • 主要组成部分
        • 代码实现
        • 工厂方法模式模式的 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 提供默认实现。
  • 增加工厂类的代价
    • 增加新的工厂类是工厂方法模式的必然代价,但这为系统的灵活性和可扩展性提供了保障。
优点和缺点
  • 优点
    • 符合开闭原则:新增产品时,只需创建新的产品类和相应的工厂类,无需修改现有代码。
    • 减少耦合:客户端代码与具体产品类解耦,依赖于抽象工厂接口,增强了系统的灵活性。
    • 扩展性强:可以方便地扩展新的产品类型,适合复杂系统的需求变化。
    • 提高代码可读性:通过明确的工厂类和产品类的分离,代码结构更加清晰。
  • 缺点
    • 类的数量增加:每新增一种产品都需要创建相应的工厂类,可能导致类的数量剧增,增加系统复杂性。
    • 实现复杂性:对于简单产品的创建,工厂方法模式可能显得过于复杂,增加不必要的开销。
    • 难以管理:如果产品种类过多,可能导致工厂类的管理变得困难。
适用场景
  • 产品族:需要创建一系列相关或相互依赖的对象时,工厂方法模式非常适合。
  • 产品类型变化频繁:当产品类型经常变化,且需要动态地扩展新产品时,工厂方法模式提供了良好的灵活性。
  • 需要解耦的系统:当系统需要将对象创建与使用分离时,工厂方法模式可以有效降低耦合度。
  • 复杂对象的创建:当对象的创建过程复杂,且可能涉及多个步骤时,工厂方法模式可以封装这些复杂性。

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

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

相关文章

笔记 5 : 彭老师课本第 5 章 , 开始代码编程

&#xff08;49&#xff09;大纲&#xff1a; &#xff08;50&#xff09; 系统&#xff1a; &#xff08;51&#xff09; 学习路线&#xff1a; &#xff08;52&#xff09;该款 soc 的内存布局&#xff1a; 细化的 SFR 地址空间 &#xff1a; &#xff08;53&#xff09; soc…

IMX8M核心板偶发系统启动失败排查实录

一. 基本情况介绍 1. 硬件方案组成 产品中采用的是IMX8M核心板的方案&#xff0c;如图1所示是产品的硬件系统整体组成示意图。 图1 产品硬件组成框图 2. 问题描述 今年5月份有一台设备出现系统偶发启动失败&#xff0c;uboot阶段都无法通过&#xff0c;表面现象是显示屏黑屏…

Android持久化技术—SharedPreferences存储

文章目录 Android持久化技术—SharedPreferences存储将数据存储到SharedPreferences中Context类中的getSharedPreferences()方法Activity类中的getPreferences()方法PreferenceManager类中的getDefaultSharedPreferences()方法 从SharedPreferences中读取数据 Android持久化技术…

【自动驾驶】ROS远程节点的分布式通信

目录 固定IP的设置将IP地址改成手动配置文件修改配置主从机的~/.bashrc 文件配置主机的 IP 地址配置从机IP ROS是一个分布式计算环境。一个运行中的ROS系统可以包含分布在多台计算机上多个节点。根据系统的配置方式&#xff0c;任何节点可能随时需要与任何其他节点进行通信。 …

XSS靶场————XSS.pwnfunction

目录 第一关&#xff1a;Ma Spaghet! 第二关&#xff1a;Jefff 第三关&#xff1a;Ugandan Knuckles​编辑 第四关&#xff1a;Ricardo Milos ​编辑 第五关&#xff1a;Ah Thats Hawt​编辑 第六关&#xff1a;Ligma 第七关&#xff1a;Mafia​编辑 第八关&#xff1a…

交易系统JVM内存优化

背景 新交易系统上线以后&#xff0c;业务指标&#xff08;成单率&#xff09;和系统指标&#xff08;CPU、QPS、JVM内存&#xff09;是我们重点关注的指标。 CPU较高&#xff1a;可以通过Arthas等工具查看繁忙线程的堆栈信息&#xff0c;定位具体的代码&#xff0c;具体分析…

谷歌浏览器字体模糊不清怎么办

许多小伙伴在使用谷歌浏览器时&#xff0c;可能都遇见过字体模糊不清的情况&#xff0c;这将对我们的浏览体验大打折扣。为了解决这以问题&#xff0c;本文将为大家带来谷歌浏览器字体模糊不清的解决方法&#xff0c;帮助你享受到更清晰舒适的阅读环境。&#xff08;本文由chro…

聚星文社AI工具官方

聚星文社是一键AI推文生成工具超强功能极速版介绍聚星文社AI工具官方https://docs.qq.com/doc/DRU1vcUZlanBKR2xy 同时集成原创和反推搬运功能 并可一键切换MJ或SD进行批量出库 一键自动智能分镜或手动快速分镜 精准排布镜头功能全预设 超简化流程 3秒即可完成参数配置全网最全…

Java 并发(五)—— 线程池

线程池核心参数&#xff1f;&#xff08;核心线程数、最大线程数、任务队列&#xff09;线程池构造方法中除了保存参数以外还要做什么事&#xff1f;&#xff08;设置线程工厂、任务拒绝策略&#xff09;提交任务时线程池要做什么&#xff1f;&#xff08;任务执行机制&#xf…

Golang Map 深度剖析:原理、实践与面试要点

嘿,小伙伴们!我是 k 哥。今天,咱们来聊聊 Map 。 在 Go 语言这个神奇的世界里,Map 这个有点神秘的数据结构一直都是开发者们特别关注的。 你是不是在用 Map 的时候,对它里面咋工作的感到好奇?是不是碰到复杂操作的时候,特别想弄明白它背后的原理?别着急,今天这篇文章…

Java流程控制06:嵌套for循环

本节教学视频链接&#xff1a;https://www.bilibili.com/video/BV12J41137hu?p41&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5https://www.bilibili.com/video/BV12J41137hu?p41&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 在Java中&#xff0c;‌嵌套for循环是指将…

使用三菱PLC源码进行PLC读取写入操作

安装 MX Component 。 我的安装地址在&#xff1a; 打开 utl 文件夹下的 Communication Settings Utility 执行。 配置PLC 添加当前需要配置的PLC 注意 logical station Namber 就是程序里需要对接的逻辑站点编号 5.配置选择对应的COM操作选择对应的cpu型型号&#xff0c;…

Ah That‘s Hawt

目录 一、题目 二、思路 三、payload 3.1 方案一 3.1 方案二 四、思考与总结 一、题目 <!-- Challenge --> <h2 id"will"></h2> <script>smith (new URL(location).searchParams.get(markassbrownlee) || "Ah Thats Hawt")sm…

甄选系列“论软件开发过程RUP及其应用”,软考高级论文,系统架构设计师论文

论文真题 RUP(Rational Unified Process)是IBM公司的一款软件开发过程产品,它提出了一整套以UML为基础的开发准则,用以指导软件开发人员以UML为基础进行软件开发。RUP汲取了各种面向对象分析与设计方法的精华,提供了一个普遍的软件过程框架,可以适应不同的软件系统、应用…

ant -design 框架以及具体调试

1.介绍 Ant-Design-Vue 是一个基于 Ant Design 设计体系的 Vue 实现。Ant Design 是由阿里巴巴开源的一个企业级 UI 设计语言&#xff0c;旨在提升用户体验和开发效率。Ant-Design-Vue 将 Ant Design 的设计理念和组件库带入了 Vue 生态系统&#xff0c;使得开发者能够在 Vue …

RabbitMQ集群 - 普通集群搭建、宕机情况

文章目录 RabbitMQ 普通集群概述集群搭建数据准备启动容器宕机情况 RabbitMQ 普通集群 概述 1&#xff09;普通模式中所有节点没有主从之分&#xff0c;所有节点的元数据&#xff08;交换机、队列、绑定等&#xff09;都是一致的. 例如只要有任意一个节点上面 新增交换机&…

迈出Python自动化测试的第一步

一、思考❓❔ 1.什么是性能自动化测试? 性能 系统负载能力超负荷运行下的稳定性系统瓶颈 自动化测试 使用程序代替手工提升测试效率 性能自动化 使用代码模拟大批量用户让用户并发请求多页面多用户并发请求采集参数&#xff0c;统计系统负载能力生成报告 2.Python中的性能自…

C++竞赛初阶L1-12-第五单元-while(27~28课)531: T456440 含 k 个 3 的数

题目内容 输入两个正整数 m 和 k&#xff0c;其中 1<m≤1015&#xff0c;1<k≤15 &#xff0c;判断 m 是否恰好含有 k 个 3&#xff0c;如果满足条件&#xff0c;则输出 YES&#xff0c;否则&#xff0c;输出 NO。 输入格式 输入一行&#xff0c;为两个整数 m,k&#x…

【js面试题】js原型,原型链?有什么特点

在 JavaScript 中&#xff0c;原型&#xff08;Prototype&#xff09;和原型链&#xff08;Prototype Chain&#xff09;是实现继承和共享属性与方法的核心机制。理解它们对于深入掌握 JavaScript 的对象模型非常重要。 原型&#xff08;Prototype&#xff09; 每个 JavaScri…

24年上半年天融信营收缩减1.8亿,亏损2.06亿

吉祥知识星球http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247485367&idx1&sn837891059c360ad60db7e9ac980a3321&chksmc0e47eebf793f7fdb8fcd7eed8ce29160cf79ba303b59858ba3a6660c6dac536774afb2a6330#rd 《网安面试指南》http://mp.weixin.qq.com/s?…