Golang设计模式工厂模式实战写法示例详解
亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《Golang设计模式工厂模式实战写法示例详解》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下设计模式、工厂模式,希望所有认真读完的童鞋们,都有实质性的提高。
拆出主板
今天带大家看一下怎么用 Go 写工厂模式的代码,我们来学习一个实战案例。这个写法笔者日常经常使用,能够很有效地帮助大家实现 Separation of Concerns。
主板就是一个程序的主流程。比如我们要基于一份学习资料来消化,吸收知识。我们可能有下面几步流程:
- 准备好笔记本;
- 打开资料;
- 阅读资料内容,思考并记录关键点到笔记本上;
- 做资料里包含的练习题;
- 归纳总结,验证掌握程度。
这个资料,可以是纸质书籍,可以是电子书,可以是某个平台的专栏,形式有很多,但我们不 care,因为在主题流程中,只需要它是个资料,有资料的能力即可。
换句话说,我们把资料转换成一个 interface,定义如下:
type KnowledgeMaterial interface{
GetContent() string
GetExercises() []string
}
能给我们主体内容,能给我们练习题,满足这两点就够了。
所以,主板本质上是不 care 具体这个资料是什么的。
扩展则是基于 interface 的实现,或者类比一下 adapter,就是个适配器。我们可以定义出来 Book, Ebook, Column 各种各样的扩展,它们都实现了这个 KnowledgeMaterial 接口。
很多同学写代码的时候,拆不开主板,不知道自己的核心流程是什么,这一点是非常重要的。拆不出来【主流程】,就意味着你需要针对某个实体实现逻辑时,直接依赖了这个【实现】。
比如我们上面的 case,没有 KnowledgeMaterial 接口,你的流程变成了,翻开纸质书第一页,看看目录,然后翻到第一章,开始阅读书上的文字。。。。
这是很可怕的一件事,意味着一旦结构变了,你的代码是不可能适配的。你会需要各种 if else 来判断到底是哪种类型。如果后来又来了一种学习资料,叫做【视频课程】,这时候怎么办呢?
没有页供你翻了,你面对的实体变成了视频内容,想要适配,就势必不是容易的事。
所以,大家一定要练习这个能力,遇到问题,思考自己的主流程是什么,拆出主板,然后明确你对业务实体的诉求是什么,能否抽象化。
是一个实现了KnowledgeMaterial 接口的任意实体就 ok?还是必须得是 Book 这个具体的结构体才 ok?
如果你需要的只是个接口,能够抽象简化,就尽量用我们今天要说的工厂模式来做,这样你的主流程心智负担会小很多,此后新增扩展成本也很小。
工厂模式流程
- 抽象出对实体的能力要求,变成接口;
- 实现工厂,支持适配器注册,支持根据类型获取对应的接口实现;
- 主流程只依赖接口完成;
- 将你的扩展,变成 adapter 适配器,实现接口所要求的的能力;
- 将你的适配器通过第二步里提到的方法,注册到工厂里。
这样的好处就在于,主板和扩展隔离,新增扩展的时候,只需要新增,不需要动主流程,不需要动其他扩展,避免了一大堆 if else 的写法。
代码实战
我们结合一开始提到的 KnowledgeMaterial 接口来简单示例一下。
抽象能力,定义接口
type KnowledgeMaterial interface{
GetContent() string
GetExercises() []string
}
实现工厂,支持注册和获取实现
新建一个 factory.go 文件,填充如下内容:
type KnowledgeAdapterFactory struct {
sync.RWMutex
adapters []KnowledgeAdapter
}
var (
knowledgeAdapterFactory = KnowledgeAdapterFactory{
adapters: []KnowledgeAdapter{},
}
)
// RegisterKnowledgeAdapter 注册新的知识资料适配器
func RegisterKnowledgeAdapter(adapter KnowledgeAdapter) {
knowledgeAdapterFactory.Lock()
knowledgeAdapterFactory.adapters = append(knowledgeAdapterFactory.adapters, adapter)
knowledgeAdapterFactory.Unlock()
}
// GetAllKnowledgeAdapters 获取所有知识资料适配器
func GetAllKnowledgeAdapters() []KnowledgeAdapter {
return knowledgeAdapterFactory.adapters
}
主流程只依赖接口完成
重点关注和 adapter 相关的逻辑,其他部分省略:
func LearnKnowledge() {
//准备好笔记本
notes := openNotesForWrite()
for _, adapter := range GetAllKnowledgeAdapters() {
content := adapter.GetContent()
// 阅读资料内容,思考并记录关键点到笔记本上
writeNotes(content)
// 做资料里包含的练习题
for _, ex := range adapter.GetExercises() {
doExecise(ex)
}
}
// 归纳总结,验证掌握程度
summary()
}
扩展 => 适配器,实现接口
新建一个包:book,用于实现纸质书籍的适配器。在其中新建 adapter.go 文件,填充如下代码
type Adapter struct {}
func (a *Adapter) GetContent() string {
return "xxx"
}
func (a *Adapter) GetExercises() []string {
return []string{"xxx"}
}
注册适配器到工厂里
这里写法其实相对灵活,很多人会选择直接在工厂定义的 factory.go 写注册逻辑,我个人不太喜欢这样。这就意味着每次新增适配器,都需要动工厂。
比较推荐直接在适配器的 init() 函数中完成注册,然后在 main 函数启动时 import 包进来,就执行了 init 函数。
这样写的好处在于当你新增一个扩展的时候,主流程和工厂都不需要动,只新增文件就好。
我们可以把上面的 adapter.go 新增一个函数即可:
type Adapter struct {}
func init() {
RegisterKnowledgeAdapter(&Adapter{})
}
func (a *Adapter) GetContent() string {
return "xxx"
}
func (a *Adapter) GetExercises() []string {
return []string{"xxx"}
}
小结
工厂模式是一个很简单,容易上手的写法,重点还是在于大家要区分开主板和扩展,通过注册方式填充适配器,而不是通过 if else 来区分。希望今天介绍的写法对你有帮助,这里还可以有很多变形,本质是类似的。
今天带大家了解了设计模式、工厂模式的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~
解析Golang中引用类型是否进行引用传递
- 上一篇
- 解析Golang中引用类型是否进行引用传递
- 下一篇
- Go语言数据结构之希尔排序示例详解
-
- Golang · Go教程 | 18分钟前 |
- Go text/template 怎么按不同格式复用同一份数据
- 344浏览 收藏
-
- Golang · Go教程 | 5小时前 | go · 文件系统 · 目录读取 · 排序 Go 文件大小 os.ReadDir
- Go os.ReadDir 怎么按文件大小筛选并稳定排序
- 282浏览 收藏
-
- Golang · Go教程 | 5小时前 |
- Go 怎么安全地批量重命名文件并支持失败回滚
- 240浏览 收藏
-
- Golang · Go教程 | 5小时前 | go · 文件遍历 · filepath.WalkDir ·
- Go filepath.WalkDir 怎么跳过隐藏目录并继续遍历
- 479浏览 收藏
-
- Golang · Go教程 | 5小时前 | 文件处理 · zip · Go教程 · Go archive/zip ZIP目录索引 FileHeader
- Go 怎么为 ZIP 文件生成目录索引而不解压内容
- 408浏览 收藏
-
- Golang · Go教程 | 6小时前 | 文件处理 · go · archive/tar · 安全解包 · Go archive/tar tar.Reader 文件解包
- Go archive/tar 怎么保留目录结构解包到指定目录
- 136浏览 收藏
-
- Golang · Go教程 | 6小时前 | 标准库 · Go教程 · IO处理 · Go 流式读取 io.Reader io.MultiReader
- Go 怎么把多个 Reader 拼成一个连续输入流
- 426浏览 收藏
-
- Golang · Go教程 | 6小时前 | go · bufio · 日志处理 · Go bufio.Scanner 日志读取
- Go bufio.Scanner 读取长日志怎么解除单行长度限制
- 140浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- SuperCLUE
- SuperCLUE是权威的中文大语言模型综合评测基准,涵盖语言理解、知识应用、AI Agent智能体及安全性等12项核心能力。通过多轮对话与客观测试,定期发布榜单与技术报告,为模型研发、优化及行业选型提供科学依据。
- 169次使用
-
- C-Eval
- 深入了解C-Eval中文评估套件,涵盖52个学科与4级难度。本文详解其功能特点、Zero-shot/Few-shot使用方法及代码示例,助您全面评测LLM中文理解与泛化能力。
- 97次使用
-
- AI Prompt Library
- 探索AI Prompt Library免费资源库,涵盖营销、写作及多场景AI提示词。兼容ChatGPT、Claude等工具,一键复制优化输出,提升工作效率。
- 18次使用
-
- LangGPT
- LangGPT是一种受编程语言启发的结构化提示词设计工具,提供双层框架、模块化模板及变量功能,帮助用户高效编写高质量Prompt。该项目已在GitHub免费开源,适用于内容创作、编程辅助等多场景。
- 31次使用
-
- ClickPrompt
- ClickPrompt是一款专为AI提示词编写者设计的开源在线工具,支持Stable Diffusion绘图、ChatGPT对话及GitHub Copilot代码辅助。提供Prompt自动生成、一键运行、社区分享及可视化优化功能,帮助用户高效获取精准AI输出。
- 69次使用
-
- Go语言设计模式之实现观察者模式解决代码臃肿
- 2022-12-23 245浏览
-
- Go语言设计模式之结构型模式
- 2022-12-23 315浏览
-
- Golang设计模式之外观模式的实现
- 2023-05-12 272浏览
-
- 一文详解Go语言中的Option设计模式
- 2023-05-13 352浏览
-
- Go Client 配置怎么设计:Functional Options 什么时候适合用,什么时候不值得
- 2026-07-16 454浏览

