生成器模式是一种创建型设计模式, 使你能够逐步构建复杂对象。 该模式允许你使用相同的创建代码生成不同类型和形式的对象。生成器模式常与链式调用结合使用。
使用场景
生成器模式常用以下场景:
- 构建复杂对象:假设我们正在开发一个游戏,需要创建一个角色对象。角色对象具有多个属性,包括姓名、等级、技能等。由于角色的构建过程可能涉及多个步骤,如设置基本属性、学习技能、装备装备等,我们可以使用生成器模式将角色对象的构建过程分解为多个步骤,并由不同的生成器逐步构建对象的各个部分。
- 隐藏构建细节:假设我们正在开发一个图形用户界面(GUI)库,需要创建窗口对象。窗口对象的构建过程可能非常复杂,涉及到设置窗口标题、大小、样式等。为了隐藏构建细节,我们可以使用生成器模式将窗口对象的构建过程封装起来,只暴露一个简单的接口供客户端使用。
- 创建不同风格的对象:假设我们正在开发一个电子商务平台,需要创建商品对象。不同类型的商品可能具有不同的属性和配置,例如电子产品、服装、食品等。我们可以定义多个不同的商品生成器来构建具有不同属性或配置的商品对象,从而满足不同类型商品的需求。
- 灵活性和可扩展性:假设我们正在开发一个游戏,需要创建不同类型的敌人对象。敌人对象的构建过程可能会随着游戏的不同版本而发生变化,因此我们希望能够轻松地替换或扩展敌人对象的构建过程。通过使用生成器模式,我们可以定义抽象的生成器接口和具体的生成器实现,从而实现敌人对象的构建逻辑的灵活替换和扩展。
复用构建逻辑:如果存在多个对象具有相似的构建逻辑,生成器模式可以帮助我们将构建逻辑抽象出来,实现代码的复用和避免重复。
代码实现
假设我们正在构建一个电子商务平台,需要创建商品对象。商品对象有多个属性,例如名称、价格、描述等,而且不同类型的商品可能有不同的配置。
首先定义一个商品结构体,并为其定义一个构建器接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| package main
import "fmt"
type Product struct { Name string Price float64 Description string }
type IBuilder interface { SetName(name string) IBuilder SetPrice(price float64) IBuilder SetDescription(description string) IBuilder Build() *Product }
|
然后根据 ProductBuilder 接口创建一个具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| type AppleProductBuilder struct { product *Product }
func NewAppleProductBuilder() *AppleProductBuilder { return &AppleProductBuilder{product: &Product{}} }
func (b *AppleProductBuilder) SetName(name string) IBuilder { b.product.Name = name return b }
func (b *AppleProductBuilder) SetPrice(price float64) IBuilder { b.product.Price = price return b }
func (b *AppleProductBuilder) SetDescription(description string) IBuilder { b.product.Description = description return b }
func (b *AppleProductBuilder) Build() *Product { return b.product }
|
最后通过与链式调用结合,来构建复杂对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| func main() { appleBuilder := NewAppleProductBuilder()
product := appleBuilder. SetName("iPhone 13"). SetPrice(999.99). SetDescription("The latest iPhone model from Apple"). Build()
fmt.Println("Product Name:", product.Name) fmt.Println("Product Price:", product.Price) fmt.Println("Product Description:", product.Description) }
|
结语
生成器模式结合链式调用,可以让代码更加优雅。当然也可以不用链式调用,只要构建器的方法不返回构建器本身即可。