go设计模式之抽象工厂模式

抽象工厂模式

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

工厂方法模式通过引入工厂等级结构,解决了简单工厂模式中工厂类职责太重的问题,但由于工厂方法模式中的每个工厂只生产一类产品,可能会导致系统中存在大量的工厂类,势必会增加系统的开销。此时,我们可以考虑将一些相关的产品组成一个“产品族”,由同一个工厂来统一生产

抽象工厂模式(Abstract Factory Pattern):提供一个接口,用于创建一系列相关或相互依赖对象的家族,而无须指定它们具体的类。

在工厂方法模式中具体工厂负责生产具体的产品,每一个具体工厂对应一种具体产品,工厂方法也具有唯一性,一般情况下,一个具体工厂中只有一个工厂方法或者一组重载的工厂方法。但是有时候我们需要一个工厂可以提供多个产品对象,而不是单一的产品对象。

  • 产品等级结构:产品等级结构即产品的继承结构,如一个抽象类是电视机,其子类有海尔电视机、海信电视机、TCL电视机,则抽象电视机与具体品牌的电视机之间构成了一个产品等级结构,抽象电视机是父类,而具体品牌的电视机是其子类。
  • 产品族:在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品,如海尔电器工厂生产的海尔电视机、海尔电冰箱,海尔电视机位于电视机产品等级结构中,海尔电冰箱位于电冰箱产品等级结构中。

当系统所提供的工厂所需生产的具体产品并不是一个简单的对象,而是多个位于不同产品等级结构中属于不同类型的具体产品时需要使用抽象工厂模式。

抽象工厂模式与工厂方法模式最大的区别在于,工厂方法模式针对的是一个产品等级结构,而抽象工厂模式则需要面对多个产品等级结构,一个工厂等级结构可以负责多个不同产品等级结构中的产品对象的创建。

工厂模式的退化

当抽象工厂模式中每一个具体工厂类只创建一个产品对象,也就是只存在一个产品等级结构时,抽象工厂模式退化成工厂方法模式;当工厂方法模式中抽象工厂与具体工厂合并,提供一个统一的工厂来创建产品对象,并将创建对象的工厂方法设计为静态方法时,工厂方法模式退化成简单工厂模式。

参与者

  • AbstractFactory

    声明一个创建抽象产品对象的操作接口。

  • ConcreteFactory

    实现创建具体产品对象的操作。

  • AbstractProduct

    为一类产品对象声明一个接口。

  • ConcreteProduct

    定义一个将被相应的具体工厂创建的产品对象。
    实现AbstractProduct接口。

  • Client

    仅使用由AbstractFactory和AbstractProduct类声明的接口。

案例1

场景:

如果你想要购买一组运动装备,需要购买鞋子和帽子,有adidas和nike品牌。相信你会想去购买同一品牌的商品, 这样商品之间能够互相搭配起来。

  • 抽象工厂接口:ISportsFactory
  • 具体工厂:AdidasFactory、NikeFactory
  • 抽象产品:IShoe、IHat
  • 具体产品:AdidasShoe、AdidaHat、NikeShoe、NikeHat

在这里插入图片描述

抽象产品

iHat.go

package maintype IHat interface {setLogo(logo string)setColor(color string)getLogo() stringgetColor() string
}

iShoe.go

package maintype IShoe interface {setLogo(logo string)setSize(size int)getLogo() stringgetSize() int
}

具体产品

adidasHat.go

package maintype AdidasHat struct {logo stringcolor string
}func (a *AdidasHat) setLogo(logo string) {a.logo = logo
}func (a *AdidasHat) getLogo() string {return a.logo
}func (a *AdidasHat) setColor(color string) {a.color = color
}func (a *AdidasHat) getColor() string {return a.color
}

adidasShoe.go

package maintype AdidasShoe struct {logo stringsize int
}func (a *AdidasShoe) setLogo(logo string) {a.logo = logo
}func (a *AdidasShoe) getLogo() string {return a.logo
}func (a *AdidasShoe) setSize(size int) {a.size = size
}func (a *AdidasShoe) getSize() int {return a.size
}

nikeHat.go

package maintype NikeHat struct {logo  stringcolor string
}func (n *NikeHat) setLogo(logo string) {n.logo = logo
}func (n *NikeHat) getLogo() string {return n.logo
}func (n *NikeHat) setColor(color string) {n.color = color
}func (n *NikeHat) getColor() string {return n.color
}

nikeShoe.go

package maintype NikesShoe struct {logo stringsize int
}func (n *NikesShoe) setLogo(logo string) {n.logo = logo
}func (n *NikesShoe) getLogo() string {return n.logo
}func (n *NikesShoe) setSize(size int) {n.size = size
}func (n *NikesShoe) getSize() int {return n.size
}

抽象工厂

package maintype ISportsFactory interface {makeShoe() IShoemakeHat() IHat
}func GetSportsFactory(brand string) ISportsFactory {if brand == "adidas" {return &AdidasFactory{}}if brand == "nike" {return &NikeFactory{}}return nil
}

具体工厂

adidasFactory.go

package maintype AdidasFactory struct {
}func (a *AdidasFactory) makeShoe() IShoe {return &AdidasShoe{logo: "adidas",size: 42,}
}func (a *AdidasFactory) makeHat() IHat {return &AdidasHat{logo:  "adidas",color: "blue",}
}

nikeFactory.go

package maintype NikeFactory struct {
}func (n *NikeFactory) makeShoe() IShoe {return &NikesShoe{logo: "nike",size: 42,}
}func (n *NikeFactory) makeHat() IHat {return &AdidasHat{logo:  "nike",color: "red",}
}

客户端

client.go

package mainimport "fmt"func main() {f := GetSportsFactory("nike")nikeshoe := f.makeShoe()fmt.Println(nikeshoe.getLogo())fmt.Println(nikeshoe.getSize())nikehat := f.makeHat()fmt.Println(nikehat.getLogo())fmt.Println(nikehat.getColor())
}

这个案例生产了鞋子、帽子,假如鞋子又分好几种,帽子也分好几种,该如何设计代码结构。

案例2

场景:

根据参数设置创建mq和storage
mq有kafka,pulsar
storage有local,minio

跟上一个例子有点不一样,这里只有一个种类,类似于只有nike品牌,nike的鞋子又有2种。

在这里插入图片描述

抽象产品接口:

type ChunkManager interface {Upload()Download()
}type MsgStream interface {Produce()Consume()
}

具体产品:

type KafkaStream struct {
}func (k *KafkaStream) Produce() {fmt.Println("Kafka produce")
}func (k *KafkaStream) Consume() {fmt.Println("Kafka Consume")
}type PulsarStream struct {
}func (p *PulsarStream) Produce() {fmt.Println("Pulsar produce")
}func (p *PulsarStream) Consume() {fmt.Println("Pulsar Consume")
}

每个产品类别的工厂

chunk:

type ChunkFactory interface {NewChunk() ChunkManager
}type ChunkFactoryImpl struct {chunkType string
}func (ck *ChunkFactoryImpl) NewChunk() ChunkManager {if ck.chunkType == "local" {return &LocalChunkManager{}}if ck.chunkType == "minio" {return &MinioChunkManager{}}return nil
}

mq:

type Mqfactory interface {NewMQ() MsgStream
}type MqfactoryImpl struct {mqType string
}func (mq *MqfactoryImpl) NewMQ() MsgStream {if mq.mqType == "kafka" {return &KafkaStream{}}if mq.mqType == "pulsar" {return &PulsarStream{}}return nil
}

抽象工厂

type Factory interface {Init(mqType string, chunkType string)MakeMq() MsgStreamMakeChunk() ChunkManager
}

具体工厂

因为只有一个类别,就用defaultFactory命名

type DefaultFactory struct {chunkFactory ChunkFactorymqfactory    Mqfactory
}func NewDefaultFactory() Factory{return &DefaultFactory{}
}func (d *DefaultFactory) Init(mqType string, chunkType string) {d.chunkFactory = &ChunkFactoryImpl{chunkType: chunkType,}d.mqfactory = &MqfactoryImpl{mqType: mqType,}
}func (d *DefaultFactory) MakeMq() MsgStream {return d.mqfactory.NewMQ()
}func (d *DefaultFactory) MakeChunk() ChunkManager {return d.chunkFactory.NewChunk()
}

客户端:

func main() {f := NewDefaultFactory()f.Init("kafka", "minio")k := f.MakeMq()k.Produce()m := f.MakeChunk()m.Upload()
}

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

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

相关文章

Angular创建项目

Angular创建项目 文章目录 Angular创建项目1. 创建项目1.1 直接安装1.2 跳过npm i安装 2. 运行程序 1. 创建项目 ng new 项目名称 1.1 直接安装 ng new angulardemo --同时会安装依赖包,执行的命令就是npm i 1.2 跳过npm i安装 ng new angulardemo --skip-inst…

Pytorch 的实际应用 学习笔记

一. 模型的下载 weights为false时则为没有提前经过训练的模型,为true时则经过了提前训练 vgg16_false torchvision.models.vgg16(weightsFalse) vgg16_true torchvision.models.vgg16(weightsTrue) 打印 二. 模型的修改 (1)添加操作 …

RabbitMQ中的交换机类型

交换机类型 可以看到,在订阅模型中,多了一个exchange角色,而且过程略有变化: Publisher:生产者,不再发送消息到队列中,而是发给交换机 Exchange:交换机,一方面&#xff…

欧科云链:为什么减半对比特币生态的影响正在逐步“减弱”?

出品|OKG Research 作者|Jason Jiang 欧科云链OKLink数据显示,比特币于区块高度840000(北京时间2024年4月20日8:09)成功完成第四次减半,比特币挖矿奖励正式由6.25BTC减少至3.125BTC。此次减半之后&#x…

Spring MVC系列之九大核心组件

概述 Spring MVC是面试必问知识点其一,Spring MVC知识体系庞杂,有以下九大核心组件: HandlerMappingHandlerAdapterHandlerExceptionResolverViewResolverRequestToViewNameTranslatorLocaleResolverThemeResolverMultipartResolverFlashMa…

中电金信:深度解析|数字化营销运营体系搭建

如何更好更快地梳理好体系搭建思路,稳步实现落地?下文将为大家明确搭建的推进步骤、执行要点,帮助商业银行理顺数字化营销运营体系的“点”“线”“面”~ 与所有转型的曲折、阵痛等特征一样,商业银行构建数字化营销运营体系过程中…

URL路由基础与Django处理请求的过程分析

1. URL路由基础 对于高质量的Web应用来讲,使用简洁、优雅的URL设计模式非常有必要。Django框架允许设计人员自由地设计URL模式,而不用受到框架本身的约束。对于URL路由来讲,其主要实现了Web服务的入口。用户通过浏览器发送过来的任何请求&am…

PyQt5中的QTablewidget

环境 PyQt5 VSCode Qt Designer生成界面 在VSCode的资源管理器中,右键选择 PYQT:New Form,打开Qt Designer 选择新建Dialog without Buttons,点击 创建 在左侧的Item Widgets中将 Table Widget拖入Dialog窗体中。 得到界面 将文件保存…

CH4INRULZ-v1靶机练习实践报告

CH4INRULZ-v1靶机练习实践报告 1 安装靶机 靶机是.ova文件,需要用VirtualBox打开,但我习惯于使用VMWare,因此修改靶机文件,使其适用于VMWare打开。 解压ova文件,得到.ovf文件和.vmdk文件。直接用VMWare打开.ovf文件即可。 2 夺…

Oceanbase体验之(一)运维管理工具OCP部署(社区版4.2.2)

资源规划建议 ocp主机1台 内存:64G CPU1:2C及以上 硬盘大于500G observer服务器3台 内存32G CPU:4C以上 硬盘大于1T 建议存储硬盘与操作系统硬盘隔开实现IO隔离 一、OBD、OCP安装包准备 [rootobserver /]# chown -R admin:admin /software/ [rootobserver /]# …

四:物联网ARM开发

一:ARM体系结构概述 1:控制外设led灯还有一些按键这些就要用到gpio,采集传感器的数据需要adc进行转化数据格式,特殊的外设和传感器是通过特殊的协议接口去进行连接的比如一些轴传感器和主控器的连接是通过spi,IIC 控制…

更新!!!Unity移动端游戏性能优化简谱

UWA官方出品,结合多年优化经验撰写了《Unity移动端游戏性能优化简谱》,文章从Unity移动端游戏优化的一些基础讨论出发,例举和分析了近几年基于Unity开发的移动端游戏项目中最为常见的部分性能问题,并展示了如何使用UWA的性能检测工…

(MSFT.O)微软2024财年Q3营收619亿美元

在科技的浩渺宇宙中,一颗璀璨星辰再度闪耀其光芒——(MSFT.O)微软公司于2024财政年度第三季展现出惊人的财务表现,实现总营业收入达到令人咋舌的6190亿美元。这一辉煌成就不仅突显了微软作为全球技术领导者之一的地位,更引发了业界内外对这家…

AIX7环境上一次艰难的Oracle打补丁经历

系统环境 AIX :7200-05-03-2148 Oracle:11.2.0.4 PSU: 11.2.0.4.201020(31718723) perl:5.28 问题一:AUTO patch #/u01/app/11.2.0/grid/OPatch/opatch auto /tmp/31718723 错误信息如下:匹配mos 2516761.1…

Kafka 3.x.x 入门到精通(05)——对标尚硅谷Kafka教程

Kafka 3.x.x 入门到精通(05)——对标尚硅谷Kafka教程 2. Kafka基础2.1 集群部署2.2 集群启动2.3 创建主题2.4 生产消息2.5 存储消息2.6 消费消息2.6.1 消费消息的基本步骤2.6.2 消费消息的基本代码2.6.3 消费消息的基本原理2.6.3.1消费者组2.6.3.1.1 消费…

美国洛杉矶站群服务器如何提高网站排名?

美国洛杉矶站群服务器怎么样?美国洛杉矶站群服务器如何提高网站排名?Rak部落小编为您整理发布美国洛杉矶站群服务器如何提高网站排名? 美国洛杉矶站群服务器可以通过以下几种方式帮助提高网站排名: - **提升网站性能**:美国站群服务器通常配备高速CPU…

LLM学习笔记-5

目录 1.多层神经网络的实现2. 训练轮次示例3. 保存并加载模型4. 使用GPU加速训练5. 使用上面所教,进行一次训练 摘要:今天想整理一下Pytorch常用操作,以便以后进行预习(不是) 1.多层神经网络的实现 这是常用的操作&a…

Elcomsoft iOS Forensics Toolkit: iPhone/iPad/iPod 设备取证工具包

天津鸿萌科贸发展有限公司是 ElcomSoft 系列取证软件的授权代理商。 Elcomsoft iOS Forensics Toolkit 软件工具包适用于取证工作,对 iPhone、iPad 和 iPod Touch 设备执行完整文件系统和逻辑数据采集。对设备文件系统制作镜像,提取设备机密&#xff08…

阿斯达年代记三强争霸服务器没反应 安装中发生错误的解决方法

阿斯达年代记三强争霸服务器没反应 安装中发生错误的解决方法 最近刚上线的由影视剧改编的游戏《阿斯达年代记三强争霸》可谓是在游戏圈内引起了轩然大波,这是一款由网石集团与龙工作室联合开发的MMORPG游戏,游戏背景设定在一个名为阿斯大陆的区域&…

vue 实现项目进度甘特图

项目需求: 实现以1天、7天、30天为周期(周期根据筛选条件选择),展示每个项目不同里程碑任务进度。 项目在Vue-Gantt-chart: 使用Vue做数据控制的Gantt图表基础上进行了改造。 有需要的小伙伴也可以直接引入插件,自己…