【Go-设计模式】建造者模式 详解

shadowLogo

概念:

  1. 建造者模式(Builder Pattern) 又叫 生成器模式,是一种 对象构建模式
    它可以将 复杂对象的建造过程 抽象出来,使这个 抽象过程 的 不同实现方法 可以构造出 不同表现(属性) 的对象
  2. 建造者模式 是 一步一步 创建一个复杂的对象,
    它允许用户只通过 指定 复杂对象 的 类型 和 内容 就可以构建它们,用户不需要知道内部的 具体构建细节


UML:

builder
建造者模式中,有如下四种角色:

  • 抽象建造者(Builder):
    该绝是用于规范产品的各个组成部分,并进行抽象,一般独立于应用程序的逻辑。
  • 具体建造者(Concrete Builder):
    该角色实现抽象建造者中定义的所有方法,并且返回一个组件好的产品实例。
  • 产品(Product):
    该角色是建造者中的复杂对象,一个系统中会有多个产品类,这些产品类不一定有共同的接口,可以是完成不相关的。
  • 指挥者(Director):
    该角色负责安排已有模块的顺序,然后告诉Builder开始建造。
    它主要有两个作用:
  1. 隔离 Client 与 对象的生产过程
  2. 负责控制 对象的生产过程

示例:

产品类:

type Product string

抽象建造者:

type Builder interface { // model构造器 接口约定
	BuildPart1()
	BuildPart2()
	BuildPart3()
	GetResult() Product
}

具体建造者:

具体建造者1:

type BuilderModel1 struct {
	result []string
}

func (this *BuilderModel1) BuildPart1() {
	this.result = append(this.result, "model1 组件1拼接成功!")
}

func (this *BuilderModel1) BuildPart2() {
	this.result = append(this.result, "model1 组件2拼接成功!")
}

func (this *BuilderModel1) BuildPart3() {
	this.result = append(this.result, "model1 组件3拼接成功!")
}

func (this *BuilderModel1) GetResult() Product {
	var resultShow string
	for _, partFun := range this.result {
		resultShow += fmt.Sprintf("%v /n", partFun)
	}
	return Product(resultShow)
}

具体建造者2:

type BuilderModel2 struct {
	result []string
}

func (this *BuilderModel2) BuildPart1() {
	this.result = append(this.result, "model2 组件1拼接成功!")
}

func (this *BuilderModel2) BuildPart2() {
	this.result = append(this.result, "model2 组件2拼接成功!")
}

func (this *BuilderModel2) BuildPart3() {
	this.result = append(this.result, "model2 组件3拼接成功!")
}

func (this *BuilderModel2) GetResult() Product {
	var resultShow string
	for _, partFun := range this.result {
		resultShow += fmt.Sprintf("%v /n", partFun)
	}
	return Product(resultShow)
}

指挥者

type Director struct { // 指挥者
	builder Builder
}

func NewDirector(builder Builder) *Director {
	return &Director{
		builder: builder,
	}
}

func (this *Director) Construct(resultType int64) Product {
	if resultType == 1 {
		this.builder.BuildPart1()
		this.builder.BuildPart2()
	} else if resultType == 2 {
		this.builder.BuildPart2()
		this.builder.BuildPart3()
	} else {
		this.builder.BuildPart1()
		this.builder.BuildPart3()
	}
	return this.builder.GetResult()
}

测试:

package main

import (
	"DemoProject/design/base23"	// 根据自己的项目路径定制
	"fmt"
)

func main() {
	model1 := base23.BuilderModel1{}
	director := base23.NewDirector(&model1)
	fmt.Printf(string(director.Construct(2)))
}

注意事项:

  1. Client 不必知道 产品内部组成的细节,
    将 产品本身 与 产品的创建过程 解耦,使得 相同的创建过程 可以创建 不同的产品对象
  2. 每一个 具体建造者 都 相对独立,而 与其他的具体建造者无关,
    因此可以很方便地 替换具体建造者 或 增加新的具体建造者,
    用户使用 不同的具体建造者 即可得到 不同的产品对象
  3. 可以更加精细地控制 产品的创建过程
    将 复杂产品的创建步骤 分解在 不同的方法中,使得 创建过程 更加清晰, 也更方便使用程序来控制创建过程
  4. 增加新的具体建造者 无须修改原有类库的代码,
    指挥者类 针对 抽象建造者类编程,系统扩展方便,符合“开闭原则”
  5. 建造者模式所创建的产品一般具有 较多的共同点,其组成部分相似,
    如果产品之间的 差异性很大,则 不适合 使用建造者模式,因此其使用范围受到一定的限制
  6. 如果产品的 内部变化复杂,可能会导致需要 定义很多具体建造者类 来实现这种变化,导致系统变得很庞大,
    因此在这种情况下,要考虑是否选择建造者模式
posted @ 2021-12-12 20:02  在下右转,有何贵干  阅读(180)  评论(0)    收藏  举报