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

GO设计模式——5、建造者模式(创建型)

目录

建造者模式(Builder Pattern)  

建造者模式的核心角色

优缺点

使用场景

注意事项

代码实现


建造者模式(Builder Pattern)  

       建造者模式(Builder Pattern)是将一个复杂对象构建与它的表示分离,使得同样的构建过程可以创建不同的表示。建造者模式是一步一步创建一个复杂的对象,它允许用户只通过指定复杂对象的类型和内容就可以构建它们,用户不需要知道内部的具体构建细节。

建造者模式的核心角色

        1、抽象建造者(Builder):是为创建一个Product对象的各个部件指定的抽象接口。

        2、具体建造者(ConcreteBuilder):实现Builder接口,构造和装配各个部件。

        3、指挥者(Director):是构建一个实用Builder接口的对象。一方面它隔离了客户与生产过程;另一方面它负责控制产品的生成过程。

        4、产品角色(Product):具体的产品

优缺点

(1)优点:

  • 分离构建过程和表示,使得构建过程更加灵活,可以构建不同的表示。
  • 可以更好地控制构建过程,隐藏具体构建细节。
  • 代码复用性高,可以在不同的构建过程中重复使用相同的建造者。

(2)缺点:

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

使用场景

        建造者模式在创建复杂对象时非常有用,特别是当对象的构建过程涉及多个步骤或参数时。它可以提供更好的灵活性和可维护性,同时使得代码更加清晰可读。

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

注意事项

        与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。

代码实现

package main

import (
    "errors"
    "fmt"
)

// Product内的参数
type ResourceParams struct {
    name     string
    maxTotal int64
    maxIdle  int64
    minIdle  int64
}

// Product接口
type ResourceProduct interface {
    show()
}

// 实际Product,有show函数
type RedisResourceProduct struct {
    resourceParams ResourceParams
}

// show成员函数,用于显示product的参数内容
func (p *RedisResourceProduct) show() {
    fmt.Printf("Product的数据为 %+v ", p.resourceParams)
}

// 资源类创建接口
type ResourceBuilder interface {
    setName(name string) ResourceBuilder
    setMaxTotal(maxTotal int64) ResourceBuilder
    setMaxIdle(maxIdle int64) ResourceBuilder
    setMinIdle(minIdle int64) ResourceBuilder
    getError() error
    build() (p ResourceProduct)
}

// 实际建造者
type RedisResourceBuilder struct {
    resourceParams ResourceParams
    err            error
}

// 设置名称
func (r *RedisResourceBuilder) setName(name string) ResourceBuilder {
    if name == "" {
       r.err = errors.New("name为空")
       return r
    }
    r.resourceParams.name = name
    fmt.Println("RedisResourceBuilder setName ", name)
    return r
}

// 设置maxTotal值,值不能小于0
func (r *RedisResourceBuilder) setMaxTotal(maxTotal int64) ResourceBuilder {
    if maxTotal <= 0 {
       r.err = errors.New("maxTotal小于0")
       return r
    }
    r.resourceParams.maxTotal = maxTotal
    fmt.Println("RedisResourceBuilder setMaxTotal ", maxTotal)
    return r
}

// 设置maxIdle值,值不能小于0
func (r *RedisResourceBuilder) setMaxIdle(maxIdle int64) ResourceBuilder {
    if maxIdle <= 0 {
       r.err = errors.New("maxIdle小于0")
       return r
    }
    r.resourceParams.maxIdle = maxIdle
    fmt.Println("RedisResourceBuilder setMaxIdle ", maxIdle)
    return r
}

// 设置minIdle值,值不能小于0
func (r *RedisResourceBuilder) setMinIdle(minIdle int64) ResourceBuilder {
    if minIdle <= 0 {
       r.err = errors.New("minIdle小于0")
       return r
    }
    r.resourceParams.minIdle = minIdle
    fmt.Println("RedisResourceBuilder setMinIdle ", minIdle)
    return r
}

// 获取错误信息
func (r *RedisResourceBuilder) getError() error {
    return r.err
}

// 构建product: 1. 做参数校验  2. 根据参数生成product
func (r *RedisResourceBuilder) build() (p ResourceProduct) {
    // 校验逻辑放到这里来做,包括必填项校验、依赖关系校验、约束条件校验等
    if r.resourceParams.name == "" {
       r.err = errors.New("name为空")
       return
    }

    if !((r.resourceParams.maxIdle == 0 && r.resourceParams.minIdle == 0 && r.resourceParams.maxTotal == 0) ||
       (r.resourceParams.maxIdle != 0 && r.resourceParams.minIdle != 0 && r.resourceParams.maxTotal != 0)) {
       r.err = errors.New("数据需要保持一致")
       return
    }

    if r.resourceParams.maxIdle > r.resourceParams.maxTotal {
       r.err = errors.New("maxIdle > maxTotal")
       return
    }
    if r.resourceParams.minIdle > r.resourceParams.maxTotal || r.resourceParams.minIdle > r.resourceParams.maxIdle {
       r.err = errors.New("minIdle > maxTotal|maxIdle")
       return
    }
    fmt.Println("RedisResourceBuilder build")
    product := &RedisResourceProduct{
       resourceParams: r.resourceParams,
    }
    return product
}

// 指挥者
type Director struct {
}

// 指挥者控制建造过程
func (d *Director) construct(builder ResourceBuilder) ResourceProduct {
    resourceProduct := builder.setName("redis").
       setMinIdle(10).
       setMaxIdle(10).
       setMaxTotal(20).
       build()

    err := builder.getError()
    if err != nil {
       fmt.Println("构建失败,原因为" + err.Error())
       return nil
    }
    return resourceProduct
}

func main() {
    builder := &RedisResourceBuilder{}

    director := &Director{}
    product := director.construct(builder)

    if product == nil {
       return
    }

    product.show()
}

http://www.kler.cn/a/161686.html

相关文章:

  • 3D编辑器教程:如何实现3D模型多材质定制效果?
  • Python——NumPy库的简单用法,超级详细教程使用
  • 【HarmonyOS NEXT】一次开发多端部署(以轮播图、Tab栏、列表为例,配合栅格布局与媒体查询,进行 UI 的一多开发)
  • ssm100医学生在线学习交流平台+vue(论文+源码)_kaic
  • 【专题】计算机网络之网络层
  • HarmonyOS 如何实现传输中的数据加密
  • 深眸科技以机器视觉高性能优势,为消费电子行业提供优质解决方案
  • vuepress路径问题,导致图片不显示
  • 十一.图像处理与光学之图像缩放方式
  • Course2-Week3-使用机器学习的建议
  • 【开源】基于Vue.js的二手车交易系统
  • 力扣102. 二叉树的层序遍历
  • GO设计模式——14、代理模式(结构型)
  • 【深度学习】迁移学习中的领域转移及迁移学习的分类
  • 2024山东健博会,第六届济南国际大健康产业博览会5月举办
  • 1.PyTorch数据结构Tensor常用操作
  • ChatGPT/GPT4科研实践篇: AI绘图+论文写作+编程
  • ChatGPT学习笔记
  • yolov5 获取漏检图片脚本
  • 【Java】图论笔记
  • 2023-12-03 C语言最小二乘法备忘
  • 零基础自学C语言|深入理解指针 ④
  • 2002-2021年全国各地级市环境规制18个相关指标数据
  • vue项目中如何引入zip压缩包之解决方案
  • html和css写去哪儿导航条
  • CefSharp 获取POST(AJAX)、GET消息返回值(request)