自己常用的几种设计模式(未完、待更新)

options模式

最常见的场景:
第三方包一般都会提供一个方法,用于设置日志类,方便用自己框架中已有的日志服务进行调试。

实例化类时, 注入方法,利用注入的方法完成类的配置实例化。

package main

import "fmt"

// DatabaseConf 定义了数据库配置
type DatabaseConf struct {
    Host     string
    Port     int
    Username string
    Password string
}

type Logger interface

func (log *Logger) Info(){

}

// GlobalConf 定义了全局配置
type GlobalConf struct {
    Database DatabaseConf
    Log Logger
}

//关注点1:给方法取别名
type GlobalConfOption func(*GlobalConf)

//关注点2: 设置对应的属性
func WithDatabase(database DatabaseConf) GlobalConfOption {
    return func(a *GlobalConf) {
        a.Database = database
    }
}

//关注点2: 设置对应的属性
func WithLogger(log Logger) GlobalConfOption {
    return func(a *GlobalConf) {
        a.Log = log
    }
}

//关注点3, 重点在入参和方法体中的遍历
func NewGlobalConf(opts ...GlobalConfOption) *GlobalConf {
    res := &GlobalConf{}

    for _, opt := range opts {
        opt(res)
    }
    return res
}

func main() {
    globalConf := NewGlobalConf()
    customDBConf := DatabaseConf{
        Host:     "localhost",
        Port:     3306,
        Username: "user",
        Password: "password",
    }

    //关注点4: 调用方法
    globalConfWithDB := NewGlobalConf(WithDatabase(customDBConf), WithLogger(logger))
}

builder模式(建造者模式)

常见场景: 一般数据库框架都提供了链式调用

额外增加结构体,利用结构体方法完成对结构体属性的赋值,每个方法返回对象本身。

package yourpackagename

import "fmt"

type DatabaseConf struct {
    Host     string
    Port     int
    Username string
    Password string
}

// GlobalConf 定义了全局配置
type GlobalConf struct {
    Database DatabaseConf
    Log Logger
}

// 关注点1: 有一个额外的机构体来处理配置
type GlobalConfBuilder struct {
    database DatabaseConf
    log  Logger
}

//关注点2: 设置属性后,返回整个对象
func (builder *GlobalConfBuilder) WithDatabase(database DatabaseConf) *GlobalConfBuilder {
    builder.database = database
    return builder
}

// 关注点3: 最后有个方法来对之前的属性全部赋值
func (builder *GlobalConfBuilder) Build() *GlobalConf {
    return &GlobalConf{
        Database: builder.database,
        // 其他配置字段...
    }
}

func NewGlobalConfBuilder() *GlobalConfBuilder {
    return &GlobalConfBuilder{}
}

func main() {
    // 关注点5: 链式调用
    globalConf := NewGlobalConfBuilder().
        WithDatabase(DatabaseConf{
            Host:     "localhost",
            Port:     3306,
            Username: "user",
            Password: "password",
        }).
        Build()
}

缺点:
如果每增加一个属性,都要写一个WithXxx()方法、修改 GlobalConf结构体、GlobalConfBuilder结构体,也是很繁琐。

期望 GlobalConf 中增加新的配置时,不要修改其余方法,且能链式调用。

改进后的

新的builder结构体上只有一个Set方法,在入参注入方法,参考options模式利用闭包来更新属性, 最后利用Build()方法来完成配置的闭环设置

type DatabaseConf struct {
    Host     string
    Port     int
    Username string
    Password string
}

// GlobalConf 定义了全局配置
type GlobalConf struct {
    Database DatabaseConf
    Log Logger
}

type connConfBuilder struct {
    conf GlobalConf
}

func NewConnConfBuilder() *connConfBuilder {
    return &connConfBuilder{}
}

func (builder *connConfBuilder) Set(setter func(*GlobalConf)) *connConfBuilder {
    setter(&builder.conf)
    return builder
}

func (builder *connConfBuilder) Build() *GlobalConf {
    return &builder.conf
}

调用案例

gConf := NewConnConfBuilder().Set(func(conf *GlobalConf) {
    conf.Log = logger #假设这里logger已经是实例化好的类
})
if useDb  {
    gConf.Set(func(conf *GlobalConf) {
        conf.DatabaseConf = dbConf  #假设时已经赋值好的变量
    })
}
gConf.Build()
本作品采用《CC 协议》,转载必须注明作者和本文链接
学过的东西能说出来那是最妙的,能复盘写下来那也不错
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!