golang创建式设计模式---工厂模式
创建式设计模式—工厂模式
目录导航
- 创建式设计模式---工厂模式
- 1)什么是工厂模式
- 2)使用场景
- 3)实现方式
- 4)实践案例
- 5)优缺点分析
1)什么是工厂模式
工厂模式(Factory Method Pattern)是一种设计模式,旨在创建对象时,将对象的创建与使用进行分离。通过定义一个工厂类,这个类具有创建不同具体产品对象的方法。用户只需与工厂类交互,告诉工厂自己想要什么类型的产品,工厂就会负责创建并返回相应的产品对象。这样做的好处是使得系统的架构更加清晰、灵活,方便扩展和维护产品的种类,同时也降低了代码之间耦合度。简单来说,就是有个专门负责生产对象的“地方”,根据需求生产出对应的对象。
其uml类图
由图可知,工厂方法模式的角色组成如下
- 工厂(Factory):声明返回的产品对象的工厂方法的接口。该方法返回的对象类型必须与产品接口类型相匹配。
- 具体工厂(ConCreateFactory):实现工厂接口的类,会重写基础工厂方法,使其返回不同类型的产品
- 产品(Product):声明产品方法的接口。对于所有由具体工厂类及其子类构建的对象,该接口是通用的。
- 具体产品(ConcreateProduct):实现产品接口的类
2)使用场景
- 在程序开发过程中,如果开发者无法预知对象的具体类型及其依赖关系,则可以使用工厂方法模式。工厂方法模式将创建产品的工厂代码与产品代码分离,从而降低代码之间的耦合度。例如,如果需要添加一种新产品,则只需创建一个新的具体工厂类,然后重写其工厂方法。
- 如果开发者希望其他开发者可以扩展软件库或框架的内部组件,则可以使用工厂模式。
- 如果一个类需要通过子类指定其创建的对象,则可以使用工厂模式
3)实现方式
package modesimport "fmt"// 定义工厂接口
type Factory interface {//定义一个工厂方法,返回ProductFacMethod(user string) Product
}
// 定义一个具体的工厂类
type ConcreateFactory struct {
}
// 再实现接口的方法
func (cf *ConcreateFactory) FacMethod(user string) Product {p := &ConcreateFactory{} //创建一个具体的工厂实例return p
}
// 定义一个产品接口
type Product interface {Use()
}
//具体的产品类
type ConcreateProduct struct {
}
func (cf *ConcreateFactory) Use() {//TODO implement mefmt.Println("生产一个产品")
}
调用main.go进行测试
package mainimport "factoryMode/modes"func main() {factory := modes.ConcreateFactory{}//生产相关的产品product := factory.FacMethod("fac1")product.Use()
}
4)实践案例
使用工厂模式演示生产两种不同品牌的鞋子(以生产出Nike
和aidas
为例子吧)
1.定义一个产品接口TShoes
,该接口有两个私有方法–setName()
和setSize()
,以及两个公共方法----GetName()
和GetSize()
再定义一个shoes
产品类,以及方法用于实现接口的方法,MakeShoes()
则是根据shoes
品牌的不同生成不同的产品对象并返回:
shoes.go
package exampleimport "fmt"// 定义鞋子产品接口
type TShoes interface {SetName(name string)SetSize(size int)GetName() stringGetSize() int
}// 定义一个shoes类
type shoes struct {name stringsize int
}func (c *shoes) SetName(name string) {c.name = name
}
func (c *shoes) GetName() string {return c.name
}func (c *shoes) SetSize(size int) {c.size = size
}
func (c *shoes) GetSize() int {return c.size
}func MakeShoes(shoesType string) (TShoes, error) {if shoesType == "Nike" {return newNike(), nil}if shoesType == "Adidas" {return newAdidas(), nil}return nil, fmt.Errorf("鞋子类型不对")
}
2.顶一个Nike产品类
package example// 生产Nike鞋子的产品类
type Nike struct {shoes
}func newNike() TShoes {return &Nike{shoes: shoes{name: "Nike shoes",size: 37,},}
}
定义Adidas产品类
package example// 生产Adidas鞋子产品
type Adidas struct {shoes
}func newAdidas() TShoes {return &Adidas{shoes: shoes{name: "Adidas shoes",size: 38,},}
}
3.main.go
进行测试
package mainimport ("factoryMode/example""fmt"
)func main() {//创建一个Nike产品对象Nike, _ := example.MakeShoes("Nike")//创建一个Adidas产品对象Adidas, _ := example.MakeShoes("Adidas")PrintInformations(Nike)fmt.Println("----------")PrintInformations(Adidas)} // 此方法用于输出相关鞋子产品的信息,比如名字和尺码
func PrintInformations(s example.TShoes) {fmt.Printf("Shoes:%s", s.GetName())fmt.Println()fmt.Printf("Size:%d", s.GetSize())
}//输出结果为,Shoes:Nike shoes
Size:37----------
Shoes:Adidas shoes
Size:38
5)优缺点分析
优点:
- 应用程序具有可扩展性。在工厂模式中,调用一个方法与新类的实现是完全分离的。这种情况对如何扩展软件有特殊的影响:工厂模式具有高度的自治性,开发者在添加新类后,无须以任何方式更改程序。
- 工厂组件具有单独可测试性。eg:如果工厂模式实现了4个或多个类,则可以单独测试每个类的功能实现
缺点:
-
系统里的类的数量会大幅度成对增加,从而提高该系统的复杂性。工厂模式的实现会导致集成类的数量大量增加,因为每个具体的产品类都需要一个具体的工厂类。尽管工厂模式有利于软件的扩展,但是会增加工作量。如果要扩展工厂模式的产品系列,则必须要调整工厂接口和相应的具体工厂类。因此,针对所需产品类型提前进行可靠规划是非常重要的。
-
工厂组件具有单独可测试性。eg:如果工厂模式实现了4个或多个类,则可以单独测试每个类的功能实现
缺点:
- 系统里的类的数量会大幅度成对增加,从而提高该系统的复杂性。工厂模式的实现会导致集成类的数量大量增加,因为每个具体的产品类都需要一个具体的工厂类。尽管工厂模式有利于软件的扩展,但是会增加工作量。如果要扩展工厂模式的产品系列,则必须要调整工厂接口和相应的具体工厂类。因此,针对所需产品类型提前进行可靠规划是非常重要的。
- 随着抽象层的引入,提高了开发者对系统的理解难度。如果下一个人要接着上一个人的进度,需要阅读和理解抽象层的代码。
相关文章:

golang创建式设计模式---工厂模式
创建式设计模式—工厂模式 目录导航 创建式设计模式---工厂模式1)什么是工厂模式2)使用场景3)实现方式4)实践案例5)优缺点分析 1)什么是工厂模式 工厂模式(Factory Method Pattern)是一种设计模式,旨在创建对象时,将对象的创建与使用进行分离。通过定义…...
高精度定位平板主要应用在哪些领域
高精度定位平板是一种集成了高精度定位技术和强大计算能力的设备,能够提供亚米级甚至厘米级的定位精度。其应用领域广泛,涵盖测绘、精准农业、工程建设、地理信息系统(GIS)、公共安全等多个方面。这种设备凭借其高精度和耐用性&am…...
conda使用常用命令
Conda是一个非常常用的Python包管理器,也是Anaconda Python发行版的一部分。它可以帮助用户安装、更新、卸载Python包,以及管理Python虚拟环境。在这篇博客中,我们将总结一些常用的Conda命令及其用法。 安装和更新Conda 在使用Conda之前&…...

22-LINUX--多线程and多进程TCP连接
一.TCP连接基础知识 1.套接字 所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程…...

像素级创意:深入浅出PixelCNN图像合成技术
参考 https://arxiv.org/pdf/1601.06759 https://blog.csdn.net/zcyzcyjava/article/details/126559327 需要熟悉熵的一些理论、和极大释然估计等价于最小化交叉熵等知识 1. pixelcnn建模方法 pixelcnn做生成模型的想必都有耳闻。它是一种自回归模型,什么是自回归…...

MyBatisPlus使用流程
引入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.4</version> </dependency> 版本号根据需要选取 在实体类上加注解声明,表信息 根据数…...

爬虫技术升级:如何结合DrissionPage和Auth代理插件实现数据采集
背景/引言 在大数据时代,网络爬虫技术已经成为数据收集的重要手段之一。爬虫技术可以自动化地从互联网上收集数据,节省大量人力和时间成本。然而,当使用需要身份验证的代理服务器时,许多现有的爬虫框架并不直接支持代理认证。这就…...

go 微服务框架kratos错误处理的使用方法及原理探究
通过go语言原生http中响应错误的实现方法,逐步了解和使用微服务框架 kratos 的错误处理方式,以及探究其实现原理。 一、go原生http响应错误信息的处理方法 处理方法: ①定义返回错误信息的结构体 ErrorResponse // 定义http返回错误信息的…...

AI播客下载:Dwarkesh Podcast(关于AI的深度访谈)
Dwarkesh Podcast 是由 Dwarkesh Patel 主持的播客,专注于深度访谈和探讨各种复杂且有趣的话题。该播客在业界获得了极高的评价,被认为是对话和思想交流的平台。 Dwarkesh Podcast 的内容涵盖了多个领域,包括经济学、哲学以及科技等。例如&am…...
C++11function包装器的使用
类模板std::function是一种通用、多态的函数包装。std::function的实例可以对任何可以调用的目标实体进行存储、 复制和调用操作。这些目标实体包括普通函数、Lambda表达式、函数指针、以及其他函数对象等。std::function对象是对 C中现有的可调用实体的一种类型安全的包裹&…...
Vue3判断变量和对象不为null和undefined
Vue3判断变量和对象不为null和undefined 一、判断变量二、判断对象 一、判断变量 在 Vue 3 中,你可以使用 JavaScript 提供的常规方式来检查变量是否不为 null 和不为 undefined。你可以分别使用严格不等运算符 ! 来比较变量是否不为 null 和不为 undefined。以下是…...

C++进阶:C++11(列表初始化、右值引用与移动构造移动赋值、可变参数模版...Args、lambda表达式、function包装器)
C进阶:C11(列表初始化、右值引用与移动构造移动赋值、可变参数模版…Args、lambda表达式、function包装器) 今天接着进行语法方面知识点的讲解 文章目录 1.统一的列表初始化1.1{}初始化1.2 initializer_listpair的补充 2.声明相关关键字2.1a…...
Vue.js Promise 与 async/await 的比较
在现代 Web 开发中,异步操作是不可避免的。在处理异步数据获取时,开发人员通常会使用 Promise 或 async/await。虽然两者都可以实现相同的功能,但它们在代码风格、可读性和错误处理等方面有所不同。本文将对这两种方法进行比较,并…...

Qt 报错总结 No suitable kits found
目录 “No suitable kits found” 解决 解决方法参考: chatGPT辅助解决QT构建报错error: multiple target patterns 我的解决方法:把语言设置为空 “No suitable kits found” 解决 没有找到合适的kits套件,在安装Qt Creator时没有安装Min…...

ThingsBoard如何拆分前后端分离启动
后端启动 前端启动 注意事项 ThingsBoard是一个开源的物联网平台,它原本的设计就考虑到了现代Web应用的前后端分离架构。尽管其核心是一个后端服务,负责设备连接、数据处理和存储等,但其用户界面是作为单独的前端应用程序实现的,…...
加载页面 跳转 新页面 vue
通常,我们点页面上的详情,或者编辑,需要加载一个新的页面出来。 vue中加载页面的方法: 在父页面中(通常是某个模块目录下的index.vue),先写这行代码: import AddEditForm from ./…...

中国主要城市房价指数数据集(2011-2024)
数据来源:东方财富网 时间跨度:2011年1月 - 2024年4月 数据范围:中国主要城市 包含指标: 日期、城市 新建商品住宅价格指数-同比 新建商品住宅价格指数-环比 新建商品住宅价格指数-定基 二手住宅价格指数-环比 二手住宅价格指…...

Creating Server TCP listening socket *:6379: listen: Unknown error
错误: 解决方法: 在redis安装路径中打开cmd命令行窗口,输入 E:\Redis-x64-3.2.100>redis-server ./redis.windows.conf结果:...

JUnit5标记测试用例
使用场景: 通过Tag对用例分组: 环境分组:测试环境、预发布环境阶段分组:冒烟用例版本分组:V1.1、V1.2 Tag标记用例: 设置标签根据标签执行 结合Maven执行结合测试套件执行 设置标签: 通过T…...

在Windows10中重命名文件和文件夹的6种方法,有你熟悉和不熟悉的
序言 你可以通过多种方式在Windows 10上重命名文件。如果每次你想更改文件名时仍右键单击并选择“重命名”,那么我们有一些技巧可以加快更改速度。 使用文件资源管理器重命名文件和文件夹 Windows 10的文件资源管理器是一个功能强大的工具。你知道吗,有四种不同的方法可以…...
零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?
一、核心优势:专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发,是一款收费低廉但功能全面的Windows NAS工具,主打“无学习成本部署” 。与其他NAS软件相比,其优势在于: 无需硬件改造:将任意W…...
在 Nginx Stream 层“改写”MQTT ngx_stream_mqtt_filter_module
1、为什么要修改 CONNECT 报文? 多租户隔离:自动为接入设备追加租户前缀,后端按 ClientID 拆分队列。零代码鉴权:将入站用户名替换为 OAuth Access-Token,后端 Broker 统一校验。灰度发布:根据 IP/地理位写…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
【python异步多线程】异步多线程爬虫代码示例
claude生成的python多线程、异步代码示例,模拟20个网页的爬取,每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程:允许程序同时执行多个任务,提高IO密集型任务(如网络请求)的效率…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
蓝桥杯 冶炼金属
原题目链接 🔧 冶炼金属转换率推测题解 📜 原题描述 小蓝有一个神奇的炉子用于将普通金属 O O O 冶炼成为一种特殊金属 X X X。这个炉子有一个属性叫转换率 V V V,是一个正整数,表示每 V V V 个普通金属 O O O 可以冶炼出 …...

Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...