当前位置: 首页 > news >正文

三、建造者模式

构造者模式(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:

...未完待续

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Kaggle克隆github项目+文件操作+Kaggle常见操作问题解决方案——一文搞定,以openpose姿态估计项目为例
  • Kafka【二】关于消费者组(Consumer Group)、分区(partition)和副本(replica)的理解
  • Disjoint-set data structure--并查集
  • 过滤器 与 拦截器
  • window下kafka3启动多个
  • C++高精度算法--加法
  • STM32外部中断(总结了易出现的BUG)
  • Windows10上Nginx如何通过自签名证书方式发布Https服务(下)
  • pycharm 2024.1下载、安装
  • 【c++】cout打印char * 或者char[]的细节详解
  • Java中的事件驱动架构(EDA)
  • 面相对象的成员介绍
  • C# 什么是属性
  • 使用twilio向手机发短信做监控报警
  • 协议转换桥+高速协议传输终端
  • $translatePartialLoader加载失败及解决方式
  • __proto__ 和 prototype的关系
  • 《剑指offer》分解让复杂问题更简单
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 2017 年终总结 —— 在路上
  • Angular数据绑定机制
  • CAP理论的例子讲解
  • EventListener原理
  • JavaScript函数式编程(一)
  • log4j2输出到kafka
  • oschina
  • php中curl和soap方式请求服务超时问题
  • SpringCloud集成分布式事务LCN (一)
  • Vue ES6 Jade Scss Webpack Gulp
  • vue:响应原理
  • vue和cordova项目整合打包,并实现vue调用android的相机的demo
  • 如何设计一个微型分布式架构?
  • 设计模式(12)迭代器模式(讲解+应用)
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 微服务框架lagom
  • 微信支付JSAPI,实测!终极方案
  • 一、python与pycharm的安装
  • 正则表达式小结
  • 字符串匹配基础上
  • 如何通过报表单元格右键控制报表跳转到不同链接地址 ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​​​​​​​ubuntu16.04 fastreid训练过程
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #{}和${}的区别是什么 -- java面试
  • #Linux(make工具和makefile文件以及makefile语法)
  • #LLM入门|Prompt#3.3_存储_Memory
  • #NOIP 2014#day.2 T1 无限网络发射器选址
  • #在 README.md 中生成项目目录结构
  • (2)STL算法之元素计数
  • (52)只出现一次的数字III
  • (php伪随机数生成)[GWCTF 2019]枯燥的抽奖
  • (多级缓存)缓存同步
  • (力扣)循环队列的实现与详解(C语言)
  • (利用IDEA+Maven)定制属于自己的jar包
  • (三)SvelteKit教程:layout 文件