Golang中“建造者+工厂”组合模式将创建逻辑分层:工厂决定类型并返回建造者,建造者链式配置后Build()生成对象,适用于HTTP客户端等复杂初始化场景。

用 Golang 实现“建造者 + 工厂”组合模式,核心是把对象的构造逻辑分层:工厂负责决定创建哪一类对象,建造者负责按需组装复杂结构。这种方式特别适合配置项多、变体多、初始化步骤繁琐的场景(比如 HTTP 客户端、数据库连接池、消息生产者等)。
工厂决定类型,建造者负责细节
工厂不直接 new 结构体,而是返回一个建造者实例;建造者提供链式方法设置字段,最后调用 Build() 得到最终对象。这样既解耦了创建逻辑,又避免了构造函数参数爆炸。
例如要支持多种日志输出器(ConsoleLogger、FileLogger、RemoteLogger),每种又有不同配置(级别、格式、缓冲区大小等):
- 定义统一接口:
type Logger interface { Log(msg string) } - 为每种实现定义专属建造者(如
ConsoleLoggerBuilder),含私有字段和链式设置方法(WithLevel(),WithFormat()) - 工厂函数根据输入返回对应建造者:
func NewLoggerBuilder(kind string) LoggerBuilder
用泛型提升建造者复用性(Go 1.18+)
若多个类型构造流程相似(比如都有 name、timeout、retry),可抽象出泛型建造者基类:
立即学习“go语言免费学习笔记(深入)”;
type Builder[T any] interface {
Build() T
}
type GenericBuilder[T any] struct {
value T
}
func (b GenericBuilder[T]) SetField(field func(T) T) GenericBuilder[T] {
b.value = field(b.value)
return b
}
再为具体类型嵌入该结构,复用通用设置逻辑,同时保留类型安全。
避免常见陷阱
建造者应是**不可变设计**:每次设置都返回新实例,或确保内部状态不会被外部意外修改(如深拷贝切片、避免暴露指针字段)。工厂返回的建造者也应是值类型或带副本语义,防止并发下状态污染。
- 不要让建造者暴露未完成的中间状态(如
Build()前字段可被随意读取) - 在
Build()中做必要校验(如必填字段是否为空),失败时 panic 或返回 error(推荐后者) - 工厂函数名建议体现意图,如
NewHTTPClientBuilder()比NewBuilder()更清晰
实际调用示例简洁直观
使用者无需关心内部结构,只管“选类型 → 配置 → 构建”:
logger := NewLoggerBuilder("file").
WithLevel("debug").
WithFilePath("/var/log/app.log").
WithBufferSize(4096).
Build()
client := NewHTTPClientBuilder().
WithTimeout(30 * time.Second).
WithRetry(3).
WithMiddleware(AuthMiddleware, TraceMiddleware).
Build()
这种写法语义明确、易扩展、测试友好——每个建造者可单独单元测试,工厂可轻松新增类型而不改调用方代码。










