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.rhkb.cn/news/317868.html

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

相关文章

06_电子设计教程基础篇(学习视频推荐)

文章目录 前言一、基础视频1、电路原理3、模电4、高频电子线路5、电力电子技术6、数学物理方法7、电磁场与电磁波8、信号系统9、自动控制原理10、通信原理11、单片机原理 二、科普视频1、工科男孙老师2、达尔闻3、爱上半导体4、华秋商城5、JT硬件乐趣6、洋桃电子 三、教学视频1…

24.4.28(板刷dp,拓扑判环,区间dp+容斥算回文串总数)

星期一: 昨晚cf又掉分,小掉不算掉 补ABC350 D atc传送门 思路:对每个连通块,使其成为一个完全图,完全图的边数为 n*(n-1)/2 , 答案加上每个连通块成为完全图后的…

VS2022 配置OpenCV开发环境详细教程

OpenCV OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,由Intel开发并首先发布于1999年。OpenCV被广泛用于实时图像处理、视频分析、物体检测、面部识别、机器人视觉以及许多其他领域。它支持C、Pytho…

远距离、高品质、低延迟、高保真——SA316无线音频模块带您探索新的音频体验

SA316系列产品分为发射端模块SA316S-TX,SA316F30和接收端模块SA316-RX,该系列方案采用了无线高品质的语音传输芯片来设计,它可以支持外部 PCM / IIS 双模数字音频接口,同时模块为客户提供了标准化的串行接口,使用者可通过串口指令…

Linux-进程调度器

1. 前言 在计算机中,进程的数量远多于cpu的数量,所以就存在,多个进程抢占一个cpu的情况,所以就需要一套规则,决定这些进程被处理的顺序,这就叫做进程调度。 在我的简单理解下,其实就是把进程放…

Docker 安装部署 postgres

Docker 安装部署 postgres 1、拉取 postgres 镜像文件 [rootiZbp19a67kznq0h0rgosuxZ ~]# docker pull postgres:latest latest: Pulling from library/postgres b0a0cf830b12: Pull complete dda3d8fbd5ed: Pull complete 283a477db7bb: Pull complete 91d2729fa4d5: Pul…

【docker】Docker开启远程访问

将构建的镜像自动上传到服务器。 需要开放 Docker 的端口,让我们在本地能连接上服务器的 Docker,这样,才能上传构建的镜像给 Docker。 开启远程访问 首先在服务器打开 Docker 的服务文件 vim /usr/lib/systemd/system/docker.service修改…

android studio项目实战——备忘录(附源码)

成果展示&#xff1a; 1.前期准备 &#xff08;1&#xff09;在配置文件中添加权限及启动页面顺序 ①展开工程&#xff0c;打开app下方的AndroidManifest.xml,添加权限&#xff0c;如下&#xff1a; <uses-permission android:name"android.permission.CAMERA"…

OpenHarmony开源软件供应链安全风险

慕冬亮&#xff0c;华中科技大学网络空间安全学院副教授&#xff0c;武汉英才&#xff0c;华中科技大学OpenHarmony技术俱乐部、开放原子开源社团指导教师。研究方向为软件与系统安全&#xff0c;在国际安全会议上发表十余篇论文&#xff0c;并获得ACM CCS 2018杰出论文奖。创立…

Grafana页面嵌入自建Web应用页面

目录 一、应用场景 二、实现方式 1、修改Grafana配置文件 2、获取监控页面url 3、隐藏左侧和顶部菜单 一、应用场景 需要将Grafana监控页面嵌入自建Web应用页面&#xff0c;使Grafana监控页面成为自建Web应用的一部分。 二、实现方式 总体思路&#xff1a;修改Grafana配…

【R语言数据分析】基本运算与数据导入速查

R语言中命名可以包含英文字母&#xff0c;下划线&#xff0c;数字&#xff0c;点&#xff0c;下划线和数字不能作为名字的开头&#xff0c;点可以开头&#xff0c;但是点开头后面不能跟数字。一般的命名就是只使用英文和下划线就够了。 四则运算 R语言的除法是即使给的两个数…

展会资讯 | 现场精彩回顾 阿尔泰科技参展2024第23届中国国际(西部)光电产业!

2024第23届中国国际&#xff08;西部&#xff09;光电产业博览会&#xff0c;在成都世纪城新国际会展中心圆满落幕&#xff01;来自各地的光电领域设备及材料厂商汇聚一堂&#xff0c;展示前沿技术及创新成果。 展会现场&#xff0c;来自全国各地的500余家企业就精密光学、信息…

进迭时空宣布开源RISC-V芯片的AI核心技术

仟江水商业电讯&#xff08;4月29日 北京 委托发布&#xff09;4月29日&#xff0c;在“创芯生生不息——进迭时空2024年度产品发布会”上&#xff0c;进迭时空CEO、创始人&#xff0c;陈志坚博士宣布将开源进迭时空在自研RISC-V AI CPU上的核心技术&#xff0c;包括AI扩展指令…

C语言/数据结构——每日一题(合并两个有序链表)

一.前言 嗨嗨嗨&#xff0c;大家好久不见&#xff01;今天我在LeetCode看到了一道单链表题&#xff1a;https://leetcode.cn/problems/merge-two-sorted-lists想着和大家分享一下&#xff0c;废话不多说&#xff0c;让我们开始今天的题目分享吧。 二.正文 1.1题目描述 1.2题…

智慧旅游驱动行业革新:智能技术引领服务全面升级,匠心打造高品质、个性化旅游新体验

一、引言 随着科技的飞速发展和信息化程度的不断提高&#xff0c;智慧旅游正逐渐成为旅游业发展的新趋势。智慧旅游&#xff0c;顾名思义&#xff0c;是以智能化技术为支撑&#xff0c;通过大数据、云计算、物联网、人工智能等先进技术的应用&#xff0c;实现旅游服务的全面升…

袁庭新ES系列17节|Spring Data Elasticsearch基础

前言 为了简化对Elasticsearch的操作Spring Data提供了Spring Data Elasticsearch。Spring Data Elasticsearch是Spring Data技术对Elasticsearch原生API封装之后的产物&#xff0c;它通过对原生API的封装&#xff0c;使得程序员可以简单的对Elasticsearch进行各种操作。接下来…

HarmonyOS 4.0(鸿蒙开发)01 - 怎么学习鸿蒙引导篇

作为公司的全栈开发工程师 以及 未来的发展是有鸿蒙这个阶段的&#xff0c;以及本身具有这个技术栈由此后续会分享自己在实战中学习到的东西&#xff0c;碰到的bug都会分享出来&#xff0c;这是引导篇期待后续的更新 学习目标&#xff1a; 理解HarmonyOS操作系统的架构和开发…

Javascript:Web APIs(一)

Javascript基础&#xff08;一&#xff09; Javascript基础&#xff08;二&#xff09; Javascript基础&#xff08;三&#xff09; Javascript基础已经结束&#xff0c;接下来我们将进入到整个Web API学习中&#xff0c;在此&#xff0c;我们将学习DOM操作&#xff0c;基本的…

普乐蛙景区vr体验馆VR游乐场设备身历其境体验

小编给大家推荐一款gao坪效产品【暗黑战车】&#xff0c;一次6人同乘&#xff0c;炫酷外观、强大性能和丰富内容适合各个年龄层客群&#xff0c;紧张刺激的VR体验让玩家沉浸在元宇宙的魅力中&#xff0c;无论是节假日还是平日&#xff0c;景区商场助力门店提高客流量和营收~ ◆…

IGM焊接机器人RTE 495伺服电机维修详情一览

在当今科技迅速发展的时代&#xff0c;机器人已成为各行各业不可或缺的重要工具。IGM机器人便是其中之一&#xff0c;其工业机械手伺服马达作为机器人的关键部件&#xff0c;确保机器人能够高效、稳定地运行。当出现IGM焊接机器人RTE 495伺服电机故障问题时&#xff0c;及时进行…