设计模式学习[13]---抽象工厂模式+简单工厂+工厂方法模式回顾

embedded/2024/12/23 4:47:14/

文章目录

  • 前言
    • 1.原理阐述
      • 1.1 说明1
      • 1.2 说明2
    • 2.举例
  • 总结

前言

之前写过一些工厂的相关内容,详情见这两篇:简单工厂与工厂方法

这篇博客主要讲抽象工厂模式

1.原理阐述

1.1 说明1

抽象工厂模式:提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。

直接看概念其实还是有点懵的,这里翻译一下。
用一个抽象的类,这个类叫做抽象工厂,去封装一系列相互依赖的实例化的过程。这个实例化涉及到互相依赖的接口,比如A里面包含了abc类型,B里面也包含了abc类型,创建a类型,其实需要依赖它是A还是B这种类型。这样讲可能还是不懂。


1.2 说明2

所以我又结合了另一本设计模式的书看,下面是另一种说法(例子来自于另一本书)。

如果一个工厂子类能够生产不止一种具有相同规格规则的怪物对象,那么就可以有效地减少所创建的工厂子类数量,这就是抽象工厂模式的核心思想

这里怪物对象的例子如下:
假如现在有三种怪物,亡灵类,元素类和机械类;还有三种战斗场地:沼泽地区、山脉地区、城镇。
那么这样的情况,整个游戏其实有9类怪物,分别是沼泽地区的三类怪物,山脉地区的三类怪物、城镇地区的三类怪物。
这样划分的是因为,每个区域的同类型怪物能力差距很大,比如沼泽里面的亡灵类怪物攻击力比城镇的亡灵类怪物攻击力高,这其实就是打游戏的时候的一个环境加成吧。

这时候需要提及了两个概念。产品等级结构产品族
将刚才提到的9种怪物放到一个坐标轴中,我们会发现,按照行的方式来看,每个怪物的种类不同,但是都位于相同场景;如果按照列的方式来看,怪物的种类都相同,但是位于不同场景。

所以如果用一个工厂子类生产一个产品族(1行),那么因为有3个产品族,所以只需要3个工厂可以生产9个产品。

说到最后,就是通过抽象工厂模式,把一个复杂的多种情况的对象,用一个简单的类别工厂作分割。对于上面的例子,把3×3的矩阵变成3个1*3的矩阵。这样每个1×3的矩阵就是一个小的工厂。回到最外层,整个创建实例的最外层的那个接口,就是抽象工厂模式的一种体现。

是不是还是晕?是的,我写到这里,感觉还没能够用非常通俗的语言说明。
我们再来看例子。

2.举例

场景:怪兽有三种类型,亡灵类、元素类、机械类。

需求:我现在要创建不同类型的怪兽对象

基本做法:创建一个怪兽类,怪兽有个属性type表示他是什么类型,要创建哪种对象就根据type类型创建具体的怪兽类,这时候用户需要知道有哪些对象,同时如果还想再加怪兽种类的话,需要在Monster类中进行拓展,类似于switch分支。每加一个类型的怪兽,就需要修改Monster类中创建子类的switch分支。

简单工厂做法:
基本做法中,这种不断修改switch分支的方式,违反了开闭原则,在软件设计中是不合理的。接下来用简单工厂模式进行优化。
我们通过创建一个MonsterFactory工厂,把根据类型实例化过程交给这个工厂类去做,那么对于Monster类来说,它是保持封闭的。如果新增加一个特殊的怪兽类,只需要让这个特殊怪兽类去继承Monster类即可,修改是在这个MonsterFactory这个抽象类中。
下面是简单工厂类图。
在这里插入图片描述

工厂方法模式:
上面这个类图中,我们其实是把这个对类的修改从Monster类移到了MonsterFactory中,但实际上对于MonsterFactory类来说,他也不满足开闭原则,因为我们要一直改这个MonsterFactory类中的switch分支来创建对象。

那么如果我们把这个switch分支用类的方式进行脱离呢?那就是工厂方法模式了。

我们对每一个特定类型的怪兽用一个工厂类去实例化,比如对于亡灵类M_Undead,我们用M_UndeadFactory工厂类去实例化它,其他的几个类也一样。
这样我们可以根据类型string字段type,去创建对应的工厂类,再具体的去调用工厂类的createMonster()函数,从而完成具体实例的创建

在这里插入图片描述

抽象工厂模式
对于我们一开始提及的需求我现在要创建不同类型的怪兽对象,那如果新增一个环境条件呢?就是我们在说明2里面提到的,沼泽,城镇,山脉地形。
那如果按照我们工厂方法模式,是不是得要创建类似于下面9个工厂类:

沼泽亡灵族工厂类
沼泽元素族工厂类
沼泽机械族工厂类
山脉亡灵族工厂类
山脉元素族工厂类
山脉机械族工厂类
城镇亡灵族工厂类
城镇元素族工厂类
城镇机械族工厂类

类图的话就是类似下面红框,不断的去继承这个M_ParFactory

在这里插入图片描述

这似乎工厂太多了吧?所以我们再回到说明2来看,引入产品等级结构产品族

这时候我们再把UML类图画一下,如下图所示。

在这里插入图片描述

这个类图中,我们创建沼泽、山脉、城镇类型的怪兽生成工厂,让一个工厂子类能够生产不止一种具有相同规格规则的怪物对象,那么就可以有效地减少所创建的工厂子类数量。

那么具体main函数的代码体现如下:

//这里省略各种类的说明,具体参考UML类图M_ParFactory* p_mou_fy=new M_Factory_Mountain();//多态工厂,山脉地区的工厂
Monster* pM1=p_mou_fy->createMonster_Element();//创建山脉地区的元素类怪物M_ParFactory* p_twn_fy=new M_Factory_Town();//多态工厂,城镇的工厂
Monster* pM2=p_twn_fy->createMonster_Undead();//创建城镇的亡灵类怪物
Monster* pM3=p_twn_fy->createMonster_Mechanic();//创建城镇的机械类怪物

在main代码中,我们把所有的怪物的创建通过一个M_ParFactory工厂指针去创建,需要什么地区的就new一个什么地区的对象,需要什么类型的怪物,就用Monster*指针去指向。
我们实际对外暴露,并给用户去使用的类实际上就是一个创建怪物的工厂指针,还有一个怪物类的指针。

写到这,应该能明白抽象工厂的意义了。减少工厂方法模式的工厂数量,减少对外暴露的接口,把细节的东西全部封装到一个接口里面。同时要满足开闭原则。

总结

工厂这个大模式的意义最主要还是在于做到软件开发过程中的开闭原则,三种工厂一般作用 的范围不太一样,下面说一下三者的区分和总结。

从代码复杂度上:简单工厂模式最简单,工厂方法次之,抽象工厂模式最复杂。把简单工厂模式中的代码修改得符合开闭原则,就变成了工厂方法模式,修改工厂方法模式的代码使得一个工厂支持对多个具体产品的生产,就变成了抽象工厂模式
从需要的工厂数量上:简单工厂模式需要的工厂数量最少,工厂方法模式需要的工厂数量最多,抽象工厂模式能够有效地减少工厂方法模式所需要的工厂数量(可以将工厂方法模式看做抽象工厂模式的一种特例——抽象工厂模式中的工作若只创建一种对象就是工厂方法模式)
从实际应用上:当项目中的产品数量比较少时考虑使用简单工厂模式,如果项目稍大一点或者为了满足开闭原则,则可以使用工厂方法模式,而对于大型项目中有众多厂商并且每个厂商都生产一系列产品时应该考虑使用抽象工厂模式


http://www.ppmy.cn/embedded/147981.html

相关文章

Neo4j插入数据逐级提升速度4倍又4倍

语雀版:https://www.yuque.com/xw76/back/dtukgqfkfwg1d6yo 目录 背景介绍初始方案Node()创建事务批量提交记录Node是否存在生成Cypher语句执行数据库参数优化切换成85k个三元组测试建索引(很显著!!!)MATCH…

Java 实现 AES 加密和解密

目录 前言 一、AES 加密算法简介 1.诞生背景 2.简介 二、AES 加密算法的核心原理 1.分组密码模式 2.密钥扩展 3.加密轮次与操作 三、AES 加密算法的优势 1.高效性 2.安全性 3.广泛的适用性 四、AES加密模式的几种方式 1.电子密码本模式(ECB&#xff0c…

【嵌入式开发笔记】OpenOCD到嵌入式调试

最近在把玩一块Risc-V的开发板,使用开发板调试时,需要用到专门的下载器和OpenOCD进行调试。 为了连接这个板子,费了九牛二虎之力。 这里简单记录一下自己的折腾经过吧。 0x00 环境准备 0x0001 调试背景 系统:Virtual Box Ub…

【软考高级】系统架构设计师复习笔记-精华版

文章目录 前言0 系统架构设计师0.1 考架构还是考系分0.2 架构核心知识0.3 架构教材变化 1 计算机操作系统1.1 cpu 组成1.2 内核的五大功能1.3 流水线技术1.4 段页式存储1.5 I/O 软件1.6 文件管理1.7 系统工程相关 2 嵌入式2.1 嵌入式技术2.2 板级支持包(BSP&#xf…

Windows开机黑屏|Windows开机黑屏只有鼠标|Windows开机不运行explorer

输入regedit打开注册表,进入以下路径 计算机\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon 左键双击右侧的 Shell 查看是否设置为 Explorer.exe

MONI后台管理系统-swagger3(springdoc-openapi)集成

springdoc-openapi Java 库有助于使用 Spring Boot 项目自动生成 API 文档。springdoc-openapi 通过在运行时检查应用程序来根据 Spring 配置、类结构和各种注释推断 API 语义。 该库会自动生成 JSON/YAML 和 HTML 格式的页面文档。生成的文档可以使用swagger-api注释进行补充。…

聚观早报 | 百度回应进军短剧;iPad Air将升级OLED

聚观早报每日整理最值得关注的行业重点事件,帮助大家及时了解最新行业动态,每日读报,就读聚观365资讯简报。 整理丨Cutie 12月18日消息 百度回应进军短剧 iPad Air将升级OLED 三星Galax S25 Ultra配色细节 一加Ace 5系列存储规格 小米…

呼入机器人:24小时客户服务的未来趋势

呼入机器人:24小时客户服务的未来趋势 作者:开源大模型智能呼叫中心系统FreeAICC,Github:https://github.com/FreeIPCC/FreeAICC 在当今快节奏的商业环境中,客户服务已成为企业竞争的核心要素之一。随着人工智能技术…