【设计模式】创建型设计模式之建造者模式(基本介绍、适用场景、go代码实例)

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

基本介绍

意图

将一个复杂的构建过程和表示相分离,使得同样的构建过程可以创建不同的表示

适用场景

在软件系统中,一个复杂对象的创建通常由多个部分组成,这些部分的组合经常变化,但是组合的算法相对稳定。

建造者模式通过将变与不变的部分分开,来解决这个问题。

  • 类的属性比较多

  • 类的属性之间有一定的依赖关系或约束条件

  • 存在必选和非必选的属性

  • 希望创建不可变的对象

关键代码

  • 建造者:创建并提供实例

  • 导演:管理建造出来的实例的依赖关系和控制构建过程

应用实例

  • 肯德基里,汉堡、可乐、薯条、鸡翅等商品是不变的,组合是经常变化的,生成不同的套餐

  • Java的StringBuilder

优点

  • 分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。

  • 可以更好地控制构建过程,隐藏具体构建细节。

  • 代码复用性高,可以在不同的构建过程中重复使用相同的建造者。

缺点

  • 如果产品的属性较少,建造者模式可能会导致代码冗余。
  • 增加了系统的类和对象数量。

## 使用场景

  • 需要生成的对象具有复杂的内部结构。
  • 需要生成的对象内部属性相互依赖。

和工厂模式的区别:建造者模式更加关注零件装配的顺序,一般用于创建参数复杂的对象;工厂模式用于创建类型相关的不同对象

结构

主要包含下面几个主要角色

  • 产品:要构建的复杂对象,通常包含多个部分或属性

  • 抽象建造者:定义了构建产品的抽象接口,包括构建产品的各个部分的方法

  • 具体建造者:实现抽象建造者接口,具体确定如何构建产品的各个部分,并负责返回最终构建的产品

  • 指导者:负责调用建造者的方法来构建产品,不了解具体的构建过程,只关心产品的构建顺序和方式

代码实例

使用Go编写建造者模式的代码其实会很长,这是它的一个缺点,如果不是参数校验逻辑很复杂的情况下一般采用第二种方式


const (
	defaultMaxTotal = 10
	defaultMaxIdle  = 9
	defaultMinIdle  = 1
)

type ResourcePoolConfig struct {
	name     string
	maxTotal int
	maxIdle  int
	minIdle  int
}

// 用于构建 ResourcePoolConfig
type ResourcePoolConfigBuilder struct {
	name     string
	maxTotal int
	maxIdle  int
	minIdle  int
}

func (r *ResourcePoolConfigBuilder) SetName(name string) error {
	if len(name) == 0 {
		return fmt.Errorf("name can not be empty")
	}
	r.name = name
	return nil
}

func (r *ResourcePoolConfigBuilder) SetMaxTotal(maxTotal int) error {
	if maxTotal <= 0 {
		return fmt.Errorf("max total cannot <= 0, input: %d", maxTotal)
	}
	r.maxTotal = maxTotal
	return nil
}

func (r *ResourcePoolConfigBuilder) SetMaxIdle(maxIdle int) error {
	if maxIdle < 0 {
		return fmt.Errorf("max idle cannot < 0, input: %d", maxIdle)
	}
	r.maxIdle = maxIdle
	return nil
}

func (r *ResourcePoolConfigBuilder) SetMinIdle(minIdle int) error {
	if minIdle < 0 {
		return fmt.Errorf("max idle cannot < 0, input: %d", minIdle)
	}
	r.minIdle = minIdle
	return nil
}
func (b *ResourcePoolConfigBuilder) Build() (*ResourcePoolConfig, error) {
	if b.name == "" {
		return nil, fmt.Errorf("name can not be empty")
	}
	if b.minIdle == 0 {
		b.minIdle = defaultMinIdle
	}
	if b.maxIdle == 0 {
		b.maxIdle = defaultMaxIdle
	}

	if b.maxTotal == 0 {
		b.maxTotal = defaultMaxTotal
	}

	if b.maxTotal < b.maxIdle {
		return nil, fmt.Errorf("max total(%d) cannot < max idle(%d)", b.maxTotal, b.maxIdle)
	}

	if b.minIdle > b.maxIdle {
		return nil, fmt.Errorf("max idle(%d) cannot < min idle(%d)", b.maxIdle, b.minIdle)
	}
	return &ResourcePoolConfig{
		name:     b.name,
		maxTotal: b.maxTotal,
		maxIdle:  b.maxIdle,
		minIdle:  b.minIdle,
	}, nil
}

第二种方式通过可变参数的方式来传递入口的参数,感觉也很容易扩展,兼容性高

func Test_NewBuilder(t *testing.T) {
	opts := []ResourcePoolConfigOptFunc{
		func(option *ResourcePoolConfigOption) {
			option.maxTotal = 20
		},
	}
	config, err := NewResourcePoolConfig("test", opts...)
	if err != nil {
		t.Fatal(err)
	}
	t.Logf("%+v", config) //&{name:test maxTotal:20 maxIdle:9 minIdle:1}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值