工厂模式属于创建型设计模式,核心思想是将对象的创建逻辑封装起来,让调用方不需要直接依赖具体对象的构造过程,降低代码耦合度。在Golang中,由于不支持传统的面向对象类继承,我们可以通过接口定义统一的行为,再结合结构体实现具体逻辑,完成工厂模式的落地。

简单工厂模式实现
简单工厂模式通过一个工厂函数,根据传入的参数返回不同的对象实例,适合对象类型较少且创建逻辑不复杂的场景。
首先定义一个统一的接口,所有具体产品都实现这个接口:
// 定义产品接口
type Product interface {
Use() string
}
// 具体产品A
type ProductA struct{}
func (p *ProductA) Use() string {
return "使用产品A"
}
// 具体产品B
type ProductB struct{}
func (p *ProductB) Use() string {
return "使用产品B"
}
接下来实现工厂函数,根据传入的类型参数返回对应的产品实例:
// 简单工厂函数
func SimpleFactory(productType string) (Product, error) {
switch productType {
case "A":
return &ProductA{}, nil
case "B":
return &ProductB{}, nil
default:
return nil, fmt.Errorf("不支持的产品类型")
}
}
调用方只需要传入对应的类型参数,不需要关心具体产品的构造细节:
func main() {
product, err := SimpleFactory("A")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(product.Use())
}
工厂方法模式实现
简单工厂模式的问题是如果需要新增产品类型,需要修改工厂函数的逻辑,违反了开闭原则。工厂方法模式将工厂的创建逻辑下沉到每个具体工厂,每个具体工厂只负责创建对应的产品,新增产品时只需要新增对应的工厂即可。
首先定义抽象工厂接口:
// 抽象工厂接口
type Factory interface {
CreateProduct() Product
}
然后为每个产品实现对应的具体工厂:
// 产品A的工厂
type FactoryA struct{}
func (f *FactoryA) CreateProduct() Product {
return &ProductA{}
}
// 产品B的工厂
type FactoryB struct{}
func (f *FactoryB) CreateProduct() Product {
return &ProductB{}
}
调用方通过对应的工厂实例获取产品:
func main() {
var factory Factory
factory = &FactoryA{}
product := factory.CreateProduct()
fmt.Println(product.Use())
}
抽象工厂模式实现
抽象工厂模式用于创建一组相关的产品族,比如不同品牌的手机和对应的充电器,每个工厂可以生产该品牌下的所有相关产品。
首先定义两个产品接口,代表不同的产品类型:
// 手机产品接口
type Phone interface {
Call() string
}
// 充电器产品接口
type Charger interface {
Charge() string
}
实现不同品牌的具体产品:
// 品牌X的手机
type PhoneX struct{}
func (p *PhoneX) Call() string {
return "品牌X手机打电话"
}
// 品牌X的充电器
type ChargerX struct{}
func (p *ChargerX) Charge() string {
return "品牌X充电器充电"
}
// 品牌Y的手机
type PhoneY struct{}
func (p *PhoneY) Call() string {
return "品牌Y手机打电话"
}
// 品牌Y的充电器
type ChargerY struct{}
func (p *ChargerY) Charge() string {
return "品牌Y充电器充电"
}
定义抽象工厂接口,包含创建所有产品族的方法:
// 抽象工厂接口
type AbstractFactory interface {
CreatePhone() Phone
CreateCharger() Charger
}
实现每个品牌的具体工厂:
// 品牌X的工厂
type FactoryX struct{}
func (f *FactoryX) CreatePhone() Phone {
return &PhoneX{}
}
func (f *FactoryX) CreateCharger() Charger {
return &ChargerX{}
}
// 品牌Y的工厂
type FactoryY struct{}
func (f *FactoryY) CreatePhone() Phone {
return &PhoneY{}
}
func (f *FactoryY) CreateCharger() Charger {
return &ChargerY{}
}
调用方通过具体工厂获取同一品牌的所有产品:
func main() {
var factory AbstractFactory
factory = &FactoryX{}
phone := factory.CreatePhone()
charger := factory.CreateCharger()
fmt.Println(phone.Call())
fmt.Println(charger.Charge())
}
不同工厂模式的选择建议
三种工厂模式各有适用场景,开发者可以根据实际需求选择:
- 简单工厂模式适合产品类型少、创建逻辑简单的场景,实现成本低,但是扩展性较差
- 工厂方法模式适合产品类型较多,需要频繁扩展新产品的场景,符合开闭原则,但是会增加类的数量
- 抽象工厂模式适合需要创建一组相关产品的场景,比如不同数据库的连接对象和查询对象,但是扩展新的产品族比较麻烦
在实际Golang开发中,不需要生硬套用设计模式,应该根据业务复杂度和后续扩展需求选择合适的实现方式,避免过度设计。