如何使用Golang实现建造者+工厂模式_组合复杂对象创建方式

14次阅读

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

如何使用Golang实现建造者+工厂模式_组合复杂对象创建方式

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()

这种写法语义明确、易扩展、测试友好——每个建造者可单独单元测试,工厂可轻松新增类型而不改调用方代码。

text=ZqhQzanResources