设计模式学习之抽象工厂模式

在这里插入图片描述
设计模式系列往期文章

  1. 设计模式学习之策略模式
  2. 设计模式学习之策略模式在前端的应用
  3. 设计模式学习之简单工厂模式
  4. 设计模式学习之工厂方法模式

如果你已经理解了工厂方法模式,那你能够很快的明白抽象工厂模式。

温习:什么是工厂方法模式

我们先温习一下什么是工厂方法模式——工厂方法模式定义了一个工厂类接口,基于这个接口实现多个具体的工厂类,每个工厂类负责生产一种产品,类图如下图所示:
在这里插入图片描述

问题引入:什么是抽象工厂模式

那么,什么是抽象工厂模式呢,我们可以把工厂方法模式看做是极端情况下的抽象工厂模式——即工厂类只生产一类产品,如果每个工厂类能够生产多类产品,这样的工厂模式就是抽象工厂模式。举个栗子,假设某个家具工厂能够生产椅子、沙发、咖啡桌等一系列家具,每种家具有有多种风格(如装饰风、维多利亚风、现代风格等),用户肯定希望买一套相同风格的家具而不是混搭,因此可以设置多个生产线,每个生产线只生产一种风格的家具,如下图所示:
在这里插入图片描述
因此家具生产这个工厂类就可能设计成下面的样子,每个工厂能够生产椅子、咖啡桌和沙发:
在这里插入图片描述
在上面这种应用场景中,我们就需要使用抽象工厂模式,其主要特点就是:工厂能够生产多种产品,同一个工厂生产出来的产品应该具有类似的风格/应用场景(正如上面的家具的例子)。类图结构如下图所示:
在这里插入图片描述

代码演示

我们继续扩展设计模式学习之工厂方法模式一文中的例子,由于环境不同,在Windows上和网页端或者MacOS系统中绘制GUI界面的代码实现肯定会有一些差别,而且工厂生产出来的组件肯定不止Button一种类型,在真实的应用场景中还会有输入框、单选框、多选框、下拉框等等组件。这个需求是不是正是抽象工厂模式的应用场景?于是可以设计出如下的类图(其实每个工厂类需要创建的产品不止两个,下图仅是示例):
在这里插入图片描述
基于类图给出如下伪代码:

// 抽象工厂接口声明了一组能返回不同抽象产品的方法。这些产品属于同一个系列
// 且在高层主题或概念上具有相关性。同系列的产品通常能相互搭配使用。系列产
// 品可有多个变体,但不同变体的产品不能搭配使用。
interface GUIFactory ismethod createButton():Buttonmethod createCheckbox():Checkbox// 具体工厂可生成属于同一变体的系列产品。工厂会确保其创建的产品能相互搭配
// 使用。具体工厂方法签名会返回一个抽象产品,但在方法内部则会对具体产品进
// 行实例化。
class WinFactory implements GUIFactory ismethod createButton():Button isreturn new WinButton()method createCheckbox():Checkbox isreturn new WinCheckbox()// 每个具体工厂中都会包含一个相应的产品变体。
class MacFactory implements GUIFactory ismethod createButton():Button isreturn new MacButton()method createCheckbox():Checkbox isreturn new MacCheckbox()// 系列产品中的特定产品必须有一个基础接口。所有产品变体都必须实现这个接口。
interface Button ismethod paint()// 具体产品由相应的具体工厂创建。
class WinButton implements Button ismethod paint() is// 根据 Windows 样式渲染按钮。class MacButton implements Button ismethod paint() is// 根据 macOS 样式渲染按钮// 这是另一个产品的基础接口。所有产品都可以互动,但是只有相同具体变体的产
// 品之间才能够正确地进行交互。
interface Checkbox ismethod paint()class WinCheckbox implements Checkbox ismethod paint() is// 根据 Windows 样式渲染复选框。class MacCheckbox implements Checkbox ismethod paint() is// 根据 macOS 样式渲染复选框。// 客户端代码仅通过抽象类型(GUIFactory、Button 和 Checkbox)使用工厂
// 和产品。这让你无需修改任何工厂或产品子类就能将其传递给客户端代码。
class Application isprivate field factory: GUIFactoryprivate field button: Buttonconstructor Application(factory: GUIFactory) isthis.factory = factorymethod createUI() isthis.button = factory.createButton()method paint() isbutton.paint()// 程序会根据当前配置或环境设定选择工厂类型,并在运行时创建工厂(通常在初
// 始化阶段)。
class ApplicationConfigurator ismethod main() isconfig = readApplicationConfigFile()if (config.OS == "Windows") thenfactory = new WinFactory()else if (config.OS == "Mac") thenfactory = new MacFactory()elsethrow new Exception("错误!未知的操作系统。")Application app = new Application(factory)

说明:对比一下工厂方法模式和抽象工厂模式,你会发现代码结构几乎一致,只是GUIFactory 中创建产品的方法变多了。

类图

抽象工厂模式的类图如下图所示:
在这里插入图片描述
对应的plantUML绘图代码为:

@startumlskinparam linetype orthopackage "Abstract Factory" <<Frame>> {interface ProductAIntf {+ method()}interface ProductBIntf {+ method()}interface FactoryIntf {+ createProductA()+ createProductB()}class ConcreteProductA1 {+ method()}class ConcreteProductA2 {+ method()}class ConcreteProductB1 {+ method()}class ConcreteProductB2 {+ method()}class ConcereteFactoryA {+ createProductA()+ createProductB()}class ConcereteFactoryB {+ createProductA()+ createProductB()}ProductAIntf <|.. ConcreteProductA1ProductAIntf <|.. ConcreteProductA2ProductBIntf <|.. ConcreteProductB1ProductBIntf <|.. ConcreteProductB2FactoryIntf <|.. ConcereteFactoryAFactoryIntf <|.. ConcereteFactoryBConcreteProductA1 <.. ConcereteFactoryAConcreteProductA2 <.. ConcereteFactoryAConcreteProductB1 <.. ConcereteFactoryBConcreteProductB2 <.. ConcereteFactoryB}
@enduml

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

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

相关文章

obs源码分析与调试:obs初始化过程

英语能力比较好的读者可以先看看官方文档&#xff1a;obsproject.com/docs/backen… OBS 的后端&#xff08;即 libobs&#xff09;使用 C 语言实现&#xff0c;提供了最核心的功能&#xff0c;包括&#xff1a;主流程、音视频子系统、通用的插件框架。 core/libobs/libobs 定…

基于微信小程序的上课签到系统(数据库+报告+文档+演示视频)

系统技术语言介绍&#xff1a; 本系统采用了SSM (Spring Spring MVC Mybatis&#xff09;架构&#xff0c; MySQL作为基础数据库&#xff0c;微信开发工具作为前端基础&#xff0c;前端采用了 wxml的设计语言&#xff0c;Idea作为后台的开发工具。 功能列表&#xff1a; 1.…

RabbitMQ 能保证消息可靠性吗

系列文章目录 消息队列选型——为什么选择RabbitMQ RabbitMQ 五种消息模型 RabbitMQ 能保证消息可靠性吗 系列文章目录前言一、消息可靠性的定义二、几种不可靠的场景三、防意外丢失1. 消息持久化2. 队列持久化3. 发布确认3.1 简单发布确认3.2 批量发布确认3.3 异步发布确认 4…

深度学习视角下的视频息肉分割

结直肠癌(CRC)是全球第二大致命癌症和第三大常见的恶性肿瘤&#xff0c;据估计每年会在全球范围内造成数百万人发病和死亡。结直肠癌患者在第一阶段的生存概率超过95%&#xff0c;但在第四和第五阶段却大幅下降到35%以下。因此&#xff0c;通过结肠镜、乙状结肠镜等筛查技术对阳…

【学习周报】

最近看过的几篇论文里&#xff0c;VALOR和InstructBLIP模型使用了cross-attention机制&#xff0c;以这两篇论文为基础着重学习cross-attention相关的代码和思路。 学习内容&#xff1a; cross-attention机制学习lstm与transformer 学习时间&#xff1a; 6.26 ~ 7.1 学习笔记…

ModaHub AI模型开源社区——向量数据库Milvus存储操作教程

目录 存储操作 数据插入 数据落盘 定时触发 客户端触发 缓冲区达到上限触发 数据合并 建立索引 删除 删除集合 删除分区 删除实体 数据段整理 数据读取 常见问题 存储操作 阅读本文前&#xff0c;请先阅读 存储相关概念。 数据插入 客户端通过调用 insert 接…

多通道分离与合并

1、分离 2、合并 Mat img imread("F:/testMap/plan.png");Mat imgs[3];split(img,imgs);//分离Mat img0,img1,img2;img0 imgs[0];img1 imgs[1]; img2 imgs[2];Mat img_H;merge(imgs,3,img_H);//合并vector<Mat> imgsV; imgsV.push_back(img0);imgsV.push_b…

git常用命令之分支操作

3. 分支 3.1 创建分支 场景1&#xff1a;创建新分支 工作中遇到的使用方式&#xff1a;1.拉取新分支&#xff0c;2.做新需求 /修复BUG &#xff0c;3.基于新分支提PR到目标分支 命令作用延展阅读git branch test11. 基于当前分支最新提交新建分支 test1(但不会切换到test1分…

Bootstrap 按钮

文章目录 Bootstrap 按钮按钮大小按钮状态激活状态禁用状态 按钮标签 Bootstrap 按钮 本章将通过实例讲解如何使用 Bootstrap 按钮。任何带有 class .btn 的元素都会继承圆角灰色按钮的默认外观。但是 Bootstrap 提供了一些选项来定义按钮的样式&#xff0c;具体如下表所示&…

Redis - Redis GEO实现经纬度测算距离,附近搜索范围

Redis GEO 主要用于存储地理位置信息&#xff0c;并对存储的信息进行操作&#xff0c;该功能在 Redis 3.2 版本新增 一、Redis GEO 操作方法 geoadd&#xff1a;添加地理位置的坐标 geopos&#xff1a;获取地理位置的坐标 geodist&#xff1a;计算两个位置之间的距离 geor…

【ArcGIS Pro二次开发】(43):线闭合

当我们需要将多段线【polyline】转为面【polygon】的时候&#xff0c;必须保证线是闭合的&#xff0c;不然是无法生成面的&#xff0c;如下图&#xff1a; 如果cad线段&#xff0c;可以在属性里将闭合选项设置为是&#xff0c;实现线的闭合&#xff1a; 但如果是在ArcGIS Pro里…

C++【初识哈希】

✨个人主页&#xff1a; 北 海 &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f383;操作环境&#xff1a; Visual Studio 2019 版本 16.11.17 文章目录 &#x1f307;前言&#x1f3d9;️正文1、哈希思想2、哈希函数2.1、哈希函数的设计原则2.2、常见的哈希函数 3、哈希…