当前位置: 首页 > news >正文

Golang单例模式和工厂模式详解

我们来详细介绍 Go 语言中的两个经典创建型设计模式单例模式(Singleton Pattern)工厂模式(Factory Pattern)

这两种模式在实际开发中非常常见,尤其是在构建配置管理、数据库连接池、日志系统等场景中。


一、单例模式(Singleton Pattern)

🎯 目的:

确保一个类在整个程序生命周期中只有一个实例,并提供一个全局访问点。

类似于“全局唯一对象”,比如:数据库连接池、配置管理器、日志记录器。


✅ Go 实现方式(推荐:sync.Once + 懒加载)

package mainimport ("fmt""sync"
)// ConfigManager 单例结构体
type ConfigManager struct {config map[string]string
}// 全局变量(私有)
var (instance *ConfigManageronce     sync.Once
)// GetInstance 返回唯一的 ConfigManager 实例
func GetInstance() *ConfigManager {once.Do(func() {instance = &ConfigManager{config: make(map[string]string),}fmt.Println("ConfigManager 初始化")})return instance
}// Set 设置配置
func (c *ConfigManager) Set(key, value string) {c.config[key] = value
}// Get 获取配置
func (c *ConfigManager) Get(key string) string {return c.config[key]
}

🔧 使用示例:

func main() {// 获取单例实例cfg1 := GetInstance()cfg1.Set("host", "localhost")// 再次获取,应是同一个实例cfg2 := GetInstance()fmt.Println(cfg2.Get("host")) // 输出: localhost// 验证是否为同一实例fmt.Printf("cfg1 == cfg2: %t\n", cfg1 == cfg2) // true
}

✅ 优点:

  • 线程安全(sync.Once 保证只初始化一次)
  • 懒加载(第一次调用才创建)
  • 全局唯一

⚠️ 注意事项:

  • 不要滥用单例(可能导致测试困难、耦合度高)
  • Go 中更推荐依赖注入(DI),但在某些场景下单例仍实用

二、工厂模式(Factory Pattern)

🎯 目的:

定义一个用于创建对象的接口,但让子类决定实例化哪一个类。Go 中没有“继承”,所以通常使用 函数返回接口 来实现。

工厂模式的核心是:解耦对象的创建与使用


1. 简单工厂模式(Simple Factory)

场景:根据类型创建不同的支付方式
package mainimport "fmt"// Payment 支付接口
type Payment interface {Pay(amount float64) string
}// Alipay 支付宝
type Alipay struct{}func (a *Alipay) Pay(amount float64) string {return fmt.Sprintf("支付宝支付 %.2f 元", amount)
}// WeChatPay 微信支付
type WeChatPay struct{}func (w *WeChatPay) Pay(amount float64) string {return fmt.Sprintf("微信支付 %.2f 元", amount)
}// UnionPay 银联支付
type UnionPay struct{}func (u *UnionPay) Pay(amount float64) string {return fmt.Sprintf("银联支付 %.2f 元", amount)
}// PaymentFactory 工厂函数
func NewPayment(method string) Payment {switch method {case "alipay":return &Alipay{}case "wechat":return &WeChatPay{}case "union":return &UnionPay{}default:panic("不支持的支付方式")}
}

🔧 使用示例:

func main() {payment := NewPayment("alipay")result := payment.Pay(99.9)fmt.Println(result) // 支付宝支付 99.90 元payment = NewPayment("wechat")result = payment.Pay(50.0)fmt.Println(result) // 微信支付 50.00 元
}

✅ 优点:调用方无需知道具体类型,只需传入字符串即可获得对应实现。


2. 抽象工厂模式(Abstract Factory)【可选扩展】

如果需要创建一系列相关或依赖对象(如:主题工厂创建按钮+文本框),可以使用抽象工厂。

type Button interface {Click()
}type TextBox interface {Input(text string)
}type UIFactory interface {CreateButton() ButtonCreateTextBox() TextBox
}type MacFactory struct{}func (m *MacFactory) CreateButton() Button { return &MacButton{} }
func (m *MacFactory) CreateTextBox() TextBox { return &MacTextBox{} }type WinFactory struct{}func (w *WinFactory) CreateButton() Button { return &WinButton{} }
func (w *WinFactory) CreateTextBox() TextBox { return &WinTextBox{} }

三、单例 vs 工厂模式对比

特性单例模式工厂模式
类型创建型创建型
目的确保唯一实例解耦对象创建过程
核心全局唯一多态创建
适用场景配置管理、连接池支付系统、插件系统、消息队列选择
Go 实现sync.Once + 全局变量函数返回接口
是否线程安全是(需正确实现)是(工厂本身无状态)

四、实际应用场景

模式应用场景
单例模式- 数据库连接池
- 日志记录器
- 配置中心
- 缓存实例(如全局 Redis 客户端)
工厂模式- 支付网关选择
- 消息队列驱动(Kafka/RabbitMQ)
- 存储后端(本地/云存储)
- API 客户端版本切换

五、注意事项(Go 特性)

  1. Go 没有构造函数:用 NewXXX() 函数代替。
  2. 优先使用接口:工厂返回接口而非具体类型。
  3. 避免全局状态滥用:单例虽方便,但会增加耦合,影响测试。
  4. 推荐依赖注入(DI):比单例更灵活(如使用 Wire、Dig 等框架)。

✅ 总结

🔑 单例模式口诀:

一生一世一双人
全局唯一,懒加载,sync.Once 保安全。

🔑 工厂模式口诀:

你告诉我类型,我给你对象
解耦创建逻辑,扩展无忧。


掌握这两个模式,你就能写出高内聚、低耦合、易扩展的 Go 程序!它们是构建大型系统的基础组件。


文章转载自:

http://Gtw4cFVG.wgbmj.cn
http://3SYXAOaM.wgbmj.cn
http://VFAYg5Sh.wgbmj.cn
http://Y2NBexn1.wgbmj.cn
http://lN0umGJ8.wgbmj.cn
http://CNpb7THi.wgbmj.cn
http://5QctJydS.wgbmj.cn
http://TyzjmUZR.wgbmj.cn
http://GCWV3h2N.wgbmj.cn
http://2ImOlKZl.wgbmj.cn
http://Vbgq93Dw.wgbmj.cn
http://dMk2lp75.wgbmj.cn
http://FNW17IH8.wgbmj.cn
http://LBXTZZ3p.wgbmj.cn
http://3FJYUIoV.wgbmj.cn
http://vUh2oYVq.wgbmj.cn
http://8ZFPBkyD.wgbmj.cn
http://AlcFx9Pf.wgbmj.cn
http://CEw72VaK.wgbmj.cn
http://X2VdZd58.wgbmj.cn
http://wBuhWVmp.wgbmj.cn
http://X4R16xwi.wgbmj.cn
http://KYzIxhxB.wgbmj.cn
http://PSLl2bJ9.wgbmj.cn
http://nPJGyMZz.wgbmj.cn
http://USChqCct.wgbmj.cn
http://0AdocWrD.wgbmj.cn
http://h2OPSSll.wgbmj.cn
http://xpZeMAE8.wgbmj.cn
http://VVDQANni.wgbmj.cn
http://www.dtcms.com/a/376362.html

相关文章:

  • Redis 分布式锁:从原理到实战的完整指南
  • 计算机网络——第一章 计算机网络体系结构
  • 【公共数据】《公共数据资源授权运营实施指南》核心观点
  • 姓名+身份证号码+人像实名认证接口-三要素身份证实名认证api
  • Linux编程笔记1-概念数据类型输入输出
  • 认知语义学对人工智能自然语言处理的影响与启示:从理论融合到未来展望
  • Markdown 介绍和使用教程
  • 实习——配置电源管理策略
  • Es6新特性总结
  • 【云原生网络篇】从 Private Endpoint 到 K8s Pod 对外注册:一次网络底层的全面探究
  • 老梁聊全栈系列:(阶段一)从单体到云原生的演进脉络
  • AI 模型训练过程中参数用BF16转向FP16的原因
  • win11,安装c++版OpenCV,带cuda
  • openEuler 24.03 (LTS-SP2)简单KVM安装+桥接模式
  • websocket 服务器往客户端发送的数据要加掩码覆盖吗?
  • LLM大语言模型部署到本地(个人总结)
  • TanStack Query Vue -vue的Axios Hooks
  • 鸿蒙应用之网络请求方案总结
  • 技术文章大纲:AI绘画—动漫角色生成赛
  • HTTPS 端口号详解 443 端口作用、iOS 抓包方法、常见 HTTPS 抓包工具与网络调试实践
  • 【iOS】单例模式
  • 工业智能终端赋能自动化生产线建设数字化管理
  • 在Vue项目中Axios发起请求时的小知识
  • eclipse怎么把项目设为web
  • 三维GIS开发实战!Cesium + CZML 实现火箭飞行与分离的 3D 动态模拟
  • Hybrid应用性能优化实战分享(本文iOS 与 H5为例,安卓同理)
  • Python 常用数据类型详解:相同点、差异与使用指南
  • Elasticsearch安装启动常见问题全解析
  • webpack turbopack vite 前端打包工具
  • NLP项目实战 | Word2Vec对比Glove进行词类比测试