【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  在下右转,有何贵干  阅读(165)  评论(0)    收藏  举报