设计模式笔记 - 生成器模式(上)

225 阅读3分钟

生成器模式 也叫建造者模式或者构建者模式。生成器模式是一种创建型设计模式,使你能够分步骤创建复杂对象。该模式允许你使用相同的创建代码生成不同类型和形式的对象。

生成器模式解决的问题是:创建对象时,初始化步骤复杂,构造函数参数很多。使用该模式能够简化初始化的过程。


实现步骤:

  • 清晰地定义通用步骤, 确保它们可以制造所有形式的产品。在基本生成器接口中声明这些步骤。
  • 为每个形式的产品创建具体生成器类, 并实现其构造步骤。
  • 考虑创建主管类。 它可以使用同一生成器对象来封装多种构造产品的方式。
  • 客户端代码会同时创建生成器和主管对象。 构造开始前, 客户端必须将生成器对象传递给主管对象。 通常情况下, 客户端只需调用主管类构造函数一次即可。 主管类使用生成器对象完成后续所有制造任务。 还有另一种方式, 那就是客户端可以将生成器对象直接传递给主管类的制造方法。
  • 只有在所有产品都遵循相同接口的情况下, 构造结果可以直接通过主管类获取。 否则, 客户端应当通过生成器获取构造结果。

优点:

  • 你可以分步创建对象, 暂缓创建步骤或递归运行创建步骤。
  • 生成不同形式的产品时, 你可以复用相同的制造代码。
  • 单一职责原则,你可以将复杂构造代码从产品的业务逻辑中分离出来

缺点:

  • 由于该模式需要新增多个类,因此代码整体复杂程度会有所增加。

下面的实例代码是根据 生成器模式 这篇文章的讲解实现的。

package main

import "fmt"

type house struct {
	wall string
	pool bool
	tree bool
}

func (h *house) show() {
	fmt.Printf("wall: %s, pool: %v, tree: %v\n", h.wall, h.pool, h.tree)
}

type builder interface {
	reset()
	setPool()
	setTree()
}

type woodHouseBuilder struct{ house }

func (b *woodHouseBuilder) setPool() {
	b.pool = true
}

func (b *woodHouseBuilder) setTree() {
	b.tree = true
}

func (b *woodHouseBuilder) reset() {
	b.wall = "wood"
	b.pool = false
	b.tree = false
}

func (b *woodHouseBuilder) get() house {
	return b.house
}

type stoneHouseBuilder struct{ house }

func (b *stoneHouseBuilder) setPool() {
	b.pool = true
}

func (b *stoneHouseBuilder) setTree() {
	b.tree = true
}

func (b *stoneHouseBuilder) reset() {
	b.wall = "stone"
	b.pool = false
	b.tree = false
}

func (b *stoneHouseBuilder) get() house {
	return b.house
}

type director struct {
	b builder
}

func (d *director) connectBuilder(b builder) {
	d.b = b
}

func (d *director) changeBuilder(b builder) {
	d.b = b
}

func (d *director) make(t string) {
	d.b.reset()

	if t == "simple" {
	} else {
		d.b.setPool()
		d.b.setTree()
	}
}

func main() {
	detor := director{}

	woodBuilder := woodHouseBuilder{}
	detor.connectBuilder(&woodBuilder)
	detor.make("all")

	woodHouse := woodBuilder.get()
	woodHouse.show() // wall: wood, pool: true, tree: true

	stoneBuilder := stoneHouseBuilder{}
	detor.changeBuilder(&stoneBuilder)
	detor.make("simple")

	stoneHouse := stoneBuilder.get()
	stoneHouse.show() // wall: stone, pool: false, tree: false
}

上面的例子,实现生成器模式的关键在于:

  • 明确builder的作用:实现具体的初始化操作
  • 明确director的作用:与特定的builder关联,对builder的初始化步骤进行选择(调用),实现builder关联的对象(上面的例子是house)的创建
  • 通过director生成的对象进行批量生成,上面的例子通过builderget方法进行获取

参考