工厂模式封装对象创建,依赖注入实现解耦。通过工厂生成Logger实例,由DI将依赖注入UserService,主函数负责装配,结合两者提升可维护性与测试性,扩展时不改业务代码。

在Go语言开发中,工厂模式与依赖注入(DI)的结合能有效提升代码的可维护性与可测试性。通过工厂创建对象,再借助依赖注入管理组件之间的依赖关系,可以让程序结构更清晰,降低耦合度。下面从实际场景出发,介绍如何将两者结合使用。
当系统中存在多种类型的服务或组件,且创建逻辑较复杂时,直接在业务代码中初始化会导致重复和紧耦合。工厂模式封装了对象的创建过程。
例如,我们有一个日志接口,支持不同实现:
type Logger interface {
Log(msg string)
}
type FileLogger struct{}
func (f *FileLogger) Log(msg string) {
fmt.Println("File log:", msg)
}
type ConsoleLogger struct{}
func (c *ConsoleLogger) Log(msg string) {
fmt.Println("Console log:", msg)
}
通过工厂来决定返回哪种日志实现:
立即学习“go语言免费学习笔记(深入)”;
type LoggerFactory struct{}
func (f *LoggerFactory) Create(loggerType string) Logger {
switch loggerType {
case "file":
return &FileLogger{}
case "console":
return &ConsoleLogger{}
default:
return &ConsoleLogger{}
}
}
有了工厂后,不应让业务模块直接调用工厂创建实例。而是通过依赖注入,将构建好的对象传递进去,避免模块感知创建逻辑。
比如一个用户服务依赖日志器:
type UserService struct {
logger Logger
}
func NewUserService(logger Logger) *UserService {
return &UserService{logger: logger}
}
func (s *UserService) Register(name string) {
s.logger.Log("User registered: " + name)
}
构造函数接收 Logger 接口,而不是内部自己 new 或调用工厂。这正是依赖注入的核心:由外部提供依赖。
真正的结合体现在应用启动阶段。在这个阶段,先通过工厂创建具体实例,然后注入到需要它的服务中。
主函数或初始化模块负责“装配”:
func main() {
factory := &LoggerFactory{}
logger := factory.Create("console") // 或从配置读取
userService := NewUserService(logger)
userService.Register("Alice")
}
这种方式下,UserService 完全不知道日志是如何创建的,只关心它能用。如果未来要加数据库日志,只需扩展工厂,不改业务代码。
当项目变大,手动管理依赖会变得繁琐。可以引入轻量级DI库如 google/wire 或 uber/fx 来自动化装配。
以 Wire 为例,定义 Provider 集合:
func ProvideLogger() Logger {
factory := &LoggerFactory{}
return factory.Create("file")
}
func ProvideUserService() *UserService {
return NewUserService(ProvideLogger())
}
Wire 在编译期生成注入代码,性能好且无运行时反射开销。
基本上就这些。工厂模式负责“造什么”,依赖注入决定“怎么给”。两者配合,让Go程序在保持简洁的同时具备良好的扩展性与测试便利性。不复杂但容易忽略。
以上就是Golang工厂模式与依赖注入结合实践的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号