概念

建造者模式一种创建型设计模式,它将一个复杂对象的构建过程与其表示分离开来,从而使得同样的构建过程可以创建不同的表示形式。

模式优点:

  • 将对象的构建过程与具体表示分离:建造者模式通过将对象的构建过程与其表示分离开来,使得可以使用相同的构建过程来创建不同的表示形式。这种分离可以提高代码的复用性和灵活性,使得代码更易于维护和扩展。

  • 易于控制对象的构建过程:建造者模式通过将对象的构建过程分解为多个简单的步骤,并通过 Director 来协调这些步骤,使得可以更加精确地控制对象的构建过程。这种精确的控制可以提高代码的可靠性和稳定性,从而减少代码出错的可能性。

  • 可以创建复杂对象:建造者模式可以通过将对象的构建过程分解为多个简单的步骤,并通过 Director 来协调这些步骤,使得可以创建复杂的对象,而不必关心其具体实现细节。这种创建复杂对象的能力可以提高代码的可重用性和灵活性,从而加快开发速度。

  • 可以改变对象的内部表示:建造者模式可以通过修改 Builder 接口或 ConcreteBuilder 结构体,来改变对象的内部表示形式,而不必改变对象的外部接口。这种改变对象内部表示形式的能力可以提高代码的可维护性和可扩展性,从而减少代码重构的需要。

实现代码

// 场景
// 现在需要生产一个汉堡
// 生产过程包括增加香肠,奶酪,生菜,番茄
// 且有固定的顺序,即必须先确定香肠,再确定生菜,奶酪,最后放番茄的顺序,顺序错了,
// 或者是少了其中任意一个步骤都不能做好一个汉堡。

// Burger 产品汉堡包
type Burger struct {
	// 香肠
	Pepperoni string
	// 🧀️
	Cheese string
	// 🥬
	Lettuce string
	// 🍅
	Tomato string
}

// GetDescription 获取描述
func (burger *Burger) GetDescription() {
	fmt.Printf("Burger 的成分是: %v,%v,%v,%v \n",
		burger.Pepperoni, burger.Cheese,
		burger.Lettuce, burger.Tomato)
}

// Builder 构建器接口
type Builder interface {
	AddPepperoni(Pepperoni string) Builder
	AddCheese(Cheese string) Builder
	AddLettuce(Lettuce string) Builder
	AddTomato(Tomato string) Builder
	Build() *Burger
}

// BurgerBuilder 具体的建造者
type BurgerBuilder struct {
	burger *Burger
}

// AddPepperoni 添加香肠
func (burgerBuilder *BurgerBuilder) AddPepperoni(Pepperoni string) Builder {
	burgerBuilder.burger.Pepperoni = Pepperoni
	return burgerBuilder
}

// AddCheese 添加 🧀️
func (burgerBuilder *BurgerBuilder) AddCheese(Cheese string) Builder {
	burgerBuilder.burger.Cheese = Cheese
	return burgerBuilder
}

// AddLettuce 添加 🥬
func (burgerBuilder *BurgerBuilder) AddLettuce(Lettuce string) Builder {
	burgerBuilder.burger.Lettuce = Lettuce
	return burgerBuilder
}

// AddTomato 添加 🍅
func (burgerBuilder *BurgerBuilder) AddTomato(Tomato string) Builder {
	burgerBuilder.burger.Tomato = Tomato
	return burgerBuilder
}

// Build 构建函数
func (burgerBuilder *BurgerBuilder) Build() *Burger {
	if burgerBuilder.burger.Pepperoni == "" || burgerBuilder.burger.Cheese == "" ||
		burgerBuilder.burger.Lettuce == "" || burgerBuilder.burger.Tomato == "" {
		fmt.Println("🍔 成分不全,制作失败!")
		return nil
	}
	return burgerBuilder.burger
}

// NewBurgerBuilder 创建一个面包构建器
func NewBurgerBuilder() *BurgerBuilder {
	return &BurgerBuilder{&Burger{}}
}

测试用例

// TestBuilder 测试
// command: go test -v builder_test.go builder.go
func TestBuilder(t *testing.T) {

	t.Log("制作第一个 🍔")
	burger1 := NewBurgerBuilder().AddPepperoni("火腿1").AddCheese("奶酪1")
  						.AddLettuce("生菜1").AddTomato("番茄1").Build()

	if burger1.Pepperoni != "火腿1" || burger1.Cheese != "奶酪1" ||
  			burger1.Lettuce != "生菜1" || burger1.Tomato != "番茄1" {
				t.Fail()
	}

	t.Log("制作第二个 🍔")
	burger2 := NewBurgerBuilder().AddPepperoni("火腿2").AddCheese("奶酪2")
  												.AddLettuce("生菜2").AddTomato("番茄2").Build()

	if burger2.Pepperoni != "火腿2" || burger2.Cheese != "奶酪2" ||
  			burger2.Lettuce != "生菜2" || burger2.Tomato != "番茄2" {
		t.Fail()
	}

	t.Log("制作第三个 🍔")
	burger3 := NewBurgerBuilder().AddPepperoni("火腿3")
  					.AddLettuce("生菜3").AddTomato("番茄3").Build()
	if burger3 != nil {
		t.Fail()
	}
}