设计模式

Go 设计模式-建造者模式_构造函数在这里插入图片描述

建造者模式

工厂模式用来创建不同、但是类型相关类型的对象(继承同一父类或者接口的一组子类),由给定的参数来决定哪种类型的对象,建造者模式是用来构建一种复杂对象,可以通过设置不同的可选参数,定制化创建不同的对象,

应用场景

  • 把类的必填属性放在构造函数中,强制创建的时候设置,如果必填属性很多,这些必填属性都需要放到构造函数中设置,那构造函数就会出现参数列表很长的问题。如果我们把必填属性通过 set() 方法设置,那校验这些属性是否填写的逻辑又无处安放。
  • 如果类属性之间有一定的依赖关系或者约束条件,我们继续用构造函数配合 set() 方法设计思路,那这些依赖关系或者约束条件又无处安放。
  • 如果我们希望创建不可变对象,也就是说,对象在创建好之后,就不能再修改内部的属性值,要实现这个功能,就不能暴露 set 方法,构造函数配合 set() 方法就不合适了。

代码例子

builder.go

package builder

//Builder 生成器接口
type Builder interface {
Part1()
Part2()
Part3()
}

type Director struct {
builder Builder
}

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

//Construct Product
func (d *Director) Construct() {
d.builder.Part1()
d.builder.Part2()
d.builder.Part3()
}

type Builder1 struct {
result string
}

func (b *Builder1) Part1() {
b.result += "1"
}

func (b *Builder1) Part2() {
b.result += "2"
}

func (b *Builder1) Part3() {
b.result += "3"
}

func (b *Builder1) GetResult() string {
return b.result
}

type Builder2 struct {
result int
}

func (b *Builder2) Part1() {
b.result += 1
}

func (b *Builder2) Part2() {
b.result += 2
}

func (b *Builder2) Part3() {
b.result += 3
}

func (b *Builder2) GetResult() int {
return b.result
}

builder_test.go

package builder

import "testing"

func TestBuilder1(t *testing.T) {
builder := &Builder1{}
director := NewDirector(builder)
director.Construct()
res := builder.GetResult()
if res != "123" {
t.Fatalf("Builder1 fail expect 123 acture %s", res)
}
}

func TestBuilder2(t *testing.T) {
builder := &Builder2{}
director := NewDirector(builder)
director.Construct()
res := builder.GetResult()
if res != 6 {
t.Fatalf("Builder2 fail expect 6 acture %d", res)
}
}

再看个例子

type Options struct {
ConnTimeout time.Duration
ReadTimeout time.Duration
RetryTime int32
}

// builder 模式
func (opt *Options) build() (err error) {
// 校验逻辑
if opt.ReadTimeout < opt.ConnTimeout {
err = errors.New("error params")
return
}
return
}
// 设置属性 ConnTimeOut
func (opt *Options) setConnTimeout(timeout time.Duration) *Options {
opt.ConnTimeout = timeout
return opt
}
// 设置属性 ReadTimeOut
func (opt *Options) setReadTimeout(timeout time.Duration) *Options {
opt.ReadTimeout = timeout
return opt
}
// 设置属性 retryTime
func (opt *Options) setRetryTime(times int32) *Options {
opt.RetryTime = times
return opt
}

builder_test.go

package main

import "testing"

func Build() {
opt := &Options{}
err := opt.
setConnTimeout(100 * time.Second).
setReadTimeout(1000 * time.Second).
setRetryTime(1).
build()
if err != nil {
panic(err)
}
fmt.Printf("BuildV1: %+v\n", opt)
}

func TestAppDemo(t *testing.T) {
Build()
}

欢迎关注公众号:程序员开发者社区

Go 设计模式-建造者模式_开发者社区_02

关注我们,了解更多




参考资料