
對象池化設計:
將池對象通過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