对象池化设计:
将池对象通过Channel方式进行借出与还入,利用Go本身的特性还能实现更多限定需求。比如利用select的分支可以进行优雅的限流、超时熔断等操作。
思路:将需要池化的对象通过Channel进行包装,使用与归还都通过Channel的方式进行
package pool
type Pool chan *Object
// 初始化池,可指定容量
func New(total int) *Pool {
p := make(Pool, total)
for i := 0; i < total; i++ {
p <- new(Object)
}
return &p
}
使用:
p := pool.New(2)
select {
case obj := <-p:
obj.Do( /*希望池中对象进行的操作*/ )
p <- obj // 使用完毕归还到池中
default:
// 池资源无剩余,延迟重试或者直接告知失败等操作
return
}
对象单例设计:
这里的实现是具有Go特色的调用方式,与double check的方式相比,更加优雅却达到相同效果
思路:利用sync包提供的once锁,从而限制创建过程仅执行一次
package singleton
type singleton map[string]string
var (
once sync.Once
instance singleton
)
func New() singleton {
once.Do(func() {
instance = make(singleton)
})
return instance
}
使用示例:
s := singleton.New()
s["this"] = "that"
s2 := singleton.New()
fmt.Println("This is ", s2["this"])
//output: This is that
工厂模式设计:
与面向对象的语言思路相同,只是这里的接口继承不是强类型的显式继承,而是更加灵活的Duck-Type方式
思路:只要是隐式实现接口Store的,都可通过Store接口接收对象,并调用接口定义的方法(里氏替换原则)
package data
import "io"
// 接口限定了能力(调用的方法)
type Store interface {
Open(string) (io.ReadWriteCloser, error)
}
type StorageType int
const (
DiskStorage StorageType = 1 << iota
TempStorage
MemoryStorage
)
func NewStore(t StorageType) Store {
// 通过枚举来创建实际创建的对象类型
switch t {
case MemoryStorage:
return newMemoryStorage( /*...*/ )
case DiskStorage:
return newDiskStorage( /*...*/ )
default:
return newTempStorage( /*...*/ )
}
}
使用示例:
s, _ := data.NewStore(data.MemoryStorage)
f, _ := s.Open("file")
n, _ := f.Write([]byte("data"))
defer f.Close()
代码来源是Github上一个开源项目,项目内容是Go相关的常用设计模式的实现,很实用易懂: https://github.com/tmrts/go-patterns
对应的Gitbook地址:http://tmrts.com/go-patterns/structural/decorator.html