三、建造者模式

embedded/2024/9/25 8:35:08/

构造者模式(Builder Pattern)使用简单的对象一步一步构建成一个复杂的对象。这种设计模式属于创建者模式,它提供了一种创建对象的最佳方式。一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。例如,计算机是由 CPU、主板、内存、硬盘、显卡、机箱、显示器、键盘、鼠标等部件组装而成的,采购员不可能自己去组装计算机,而是将计算机的配置要求告诉计算机销售公司,计算机销售公司安排技术人员去组装计算机,然后再交给要买计算机的采购员。

主要组成部分:

  1. 产品(Product)

    • 需要构建的复杂对象,通常是一个包含多个属性的类。
  2. 构造器接口(Builder)

    • 定义了构建产品的接口,通常包括设置产品各个部分的方法。
  3. 具体构建者(Concrete Builder)

    • 实现了构造器接口,负责具体产品的构建过程。通常还提供一个方法用于获取最终产品。
  4. 指挥者(Director)

    • 负责管理构建过程,调用构建者的具体方法来构建产品。
GO: 

其实在 Golang 中对于创建类参数比较多的对象的时候,我们常见的做法是必填参数直接传递,可选参数通过传递可变的方法进行创建。

方式一:使用 Go 编写建造者模式的代码其实会很长,这些是它的一个缺点,所以如果不是参数的校验逻辑很复杂的情况下一般我们在 Go 中不会采用这种方式,而会采用后面的另外一种方式
package builderimport "fmt"const (defaultMaxTotal = 10defaultMaxIdle  = 9defaultMinIdle  = 1
)// ResourcePoolConfig resource pool
type ResourcePoolConfig struct {name     stringmaxTotal intmaxIdle  intminIdle  int
}// ResourcePoolConfigBuilder 用于构建 ResourcePoolConfig
type ResourcePoolConfigBuilder struct {name     stringmaxTotal intmaxIdle  intminIdle  int
}// SetName SetName
func (b *ResourcePoolConfigBuilder) SetName(name string) error {if name == "" {return fmt.Errorf("name can not be empty")}b.name = namereturn nil
}// SetMinIdle SetMinIdle
func (b *ResourcePoolConfigBuilder) SetMinIdle(minIdle int) error {if minIdle < 0 {return fmt.Errorf("max tatal cannot < 0, input: %d", minIdle)}b.minIdle = minIdlereturn nil
}// SetMaxIdle SetMaxIdle
func (b *ResourcePoolConfigBuilder) SetMaxIdle(maxIdle int) error {if maxIdle < 0 {return fmt.Errorf("max tatal cannot < 0, input: %d", maxIdle)}b.maxIdle = maxIdlereturn nil
}// SetMaxTotal SetMaxTotal
func (b *ResourcePoolConfigBuilder) SetMaxTotal(maxTotal int) error {if maxTotal <= 0 {return fmt.Errorf("max tatal cannot <= 0, input: %d", maxTotal)}b.maxTotal = maxTotalreturn nil
}// Build Build
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 TestBuilder(t *testing.T) {tests := []struct {name    stringbuilder *ResourcePoolConfigBuilderwant    *ResourcePoolConfigwantErr bool}{{name: "name empty",builder: &ResourcePoolConfigBuilder{name:     "",maxTotal: 0,},want:    nil,wantErr: true,},{name: "maxIdle < minIdle",builder: &ResourcePoolConfigBuilder{name:     "test",maxTotal: 0,maxIdle:  10,minIdle:  20,},want:    nil,wantErr: true,},{name: "success",builder: &ResourcePoolConfigBuilder{name: "test",},want: &ResourcePoolConfig{name:     "test",maxTotal: defaultMaxTotal,maxIdle:  defaultMaxIdle,minIdle:  defaultMinIdle,},wantErr: false,},}for _, tt := range tests {t.Run(tt.name, func(t *testing.T) {got, err := tt.builder.Build()fmt.Printf("Build() error = %v, wantErr %v\n", err, tt.wantErr)fmt.Println(got)})}}

方式二:GO常用的参数传递方法 
package builderimport "fmt"const (defaultMaxTotal = 10defaultMaxIdle  = 9defaultMinIdle  = 1
)// ResourcePoolConfig resource pool
type ResourcePoolConfig struct {name     stringmaxTotal intmaxIdle  intminIdle  int
}// ResourcePoolConfigOption resource pool
type ResourcePoolConfigOption struct {maxTotal intmaxIdle  intminIdle  int
}// ResourcePoolConfigOptFunc to set option
type ResourcePoolConfigOptFunc func(option *ResourcePoolConfigOption)// NewResourcePoolConfig NewResourcePoolConfig
func NewResourcePoolConfig(name string, opts ...ResourcePoolConfigOptFunc) (*ResourcePoolConfig, error) {if name == "" {return nil, fmt.Errorf("name can not be empty")}option := &ResourcePoolConfigOption{maxTotal: 10,maxIdle:  9,minIdle:  1,}for _, opt := range opts {opt(option)}if option.maxTotal < 0 || option.maxIdle < 0 || option.minIdle < 0 {return nil, fmt.Errorf("args err, option: %v", option)}if option.maxTotal < option.maxIdle || option.minIdle > option.maxIdle {return nil, fmt.Errorf("args err, option: %v", option)}return &ResourcePoolConfig{name:     name,maxTotal: option.maxTotal,maxIdle:  option.maxIdle,minIdle:  option.minIdle,}, nil
}
func TestBuilder(t *testing.T) {type args struct {name stringopts []ResourcePoolConfigOptFunc}tests := []struct {name    stringargs    argswant    *ResourcePoolConfigwantErr bool}{{name: "name empty",args: args{name: "",},want:    nil,wantErr: true,},{name: "success",args: args{name: "test",opts: []ResourcePoolConfigOptFunc{func(option *ResourcePoolConfigOption) {option.minIdle = 2},func(option *ResourcePoolConfigOption) {option.maxTotal = 100},},},want: &ResourcePoolConfig{name:     "test",maxTotal: 10,maxIdle:  9,minIdle:  2,},wantErr: false,},}for _, tt := range tests {t.Run(tt.name, func(t *testing.T) {got, err := NewResourcePoolConfig(tt.args.name, tt.args.opts...)require.Equalf(t, tt.wantErr, err != nil, "error = %v, wantErr %v", err, tt.wantErr)assert.Equal(t, tt.want, got)})}
}

JAVA:

...未完待续


http://www.ppmy.cn/embedded/105381.html

相关文章

三根K线形态介绍

一般涉及K线的现货黄金知识&#xff0c;更多的是谈及一根K线&#xff0c;或者两根K线&#xff0c;但很少谈及更多的K线。但其实三根K线也是现货黄金知识中一个很重要的环节&#xff0c;也涉及一些比较重要的内容。所以投资者要学习现货黄金知识&#xff0c;也需要学习这些三根K…

数学建模强化宝典(4)fminunc

一、介绍 fminunc 是 MATLAB 中用于求解无约束多变量非线性优化问题的函数。它尝试找到给定函数的最小值点&#xff0c;不需要用户提供函数的导数信息&#xff08;尽管如果提供了导数信息&#xff0c;算法通常会更快更准确地收敛&#xff09;。fminunc 使用的是拟牛顿法&#x…

fastchat与autogen使用要点澄清

说明&#xff1a; 本文重点是想使用autogen构建智能体&#xff0c;并且想要通过加载本地模型来构建&#xff0c;以灵活使用。但是autogen重点是以API调用支持openai, mistral等大模型使用的&#xff0c;对于使用国内的一些模型不是那么友好方便。然后在查找方法的过程中&#x…

检测文件解析漏洞的工具

免责声明此文档仅限于学习讨论与技术知识的分享&#xff0c;不得违反当地国家的法律法规。对于传播、利用文章中提供的信息而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;本文作者不为此承担任何责任&#xff0c;一旦造成后果请自行承担&…

不再畏惧猫咪浮毛,希喂、安德迈、美的宠物空气净化器性能PK

夏天来了&#xff0c;宠物换毛季加上天气闷热&#xff0c;难消的异味和漫天乱飞的猫毛双重夹击&#xff0c;家里的空气质量直线下降。还是鼻炎患者的我感到非常不适&#xff0c;有股想把家里两只毛孩子逐出家门的冲动。每天不是梳毛就是在吸毛的路上&#xff0c;猫咪们还爱到处…

【STM32+HAL库】---- 按键中断控制LED

硬件开发板&#xff1a;STM32G0B1RET6 软件平台&#xff1a;cubemaxkeilVScode1 新建cubemax工程 1.1 配置系统时钟树 1.2 配置相关GPIO引脚 ①LED由PC13引脚控制 选择PA5引脚&#xff0c;GPIO_Output模式 GPIO模式配置&#xff1a; ②按键开关由PC13引脚控制 选择PC13引…

Pytorch安装 CUDA Driver、CUDA Runtime、CUDA Toolkit、nvcc、cuDNN解释与辨析

Pytorch的CPU版本与GPU版本 Pytorch的CPU版本 仅在 CPU 上运行&#xff0c;适用于没有显卡或仅使用 CPU 的机器。安装方式相对简单&#xff0c;无需额外配置 CUDA 或 GPU 驱动程序。使用方式与 GPU 版相同&#xff0c;唯一不同的是计算将自动在 CPU 上进行。 Pytorch的GPU版…

系统思考—关键决策

结‮影构‬响行为&#xff0c;精‮决准‬策创造价值&#xff01; 最‮身近‬边很多‮伙小‬伴找我“助力”&#xff0c;父‮也母‬经常发‮息信‬让我帮忙&#xff0c;忍‮住不‬研究了一下‮些这‬助力活动的“玩法”。说实话&#xff0c;这‮设种‬计从‮构结‬上真‮很的‬…