自己常用的几种设计模式(未完、待更新)
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 协议》,转载必须注明作者和本文链接