Go设计模式之Factory
Overview
Factory - 工厂模式
工厂模式在Go中使用的非常广泛,比如常用于数据的读写模块。假设我们需要从某种介质中读取数据,并将更新后的结果保存到该介质中。考虑到以后可能更换为其他类型的介质,为了避免日后更换介质而大面积变更代码,我们就会用到本模式。
实现
1.定义工厂方法所创建对象的接口
假设我们的存储模块只有Read和Write两个功能,我们需要先定义存储器inteface。
1package store
2
3import "io"
4
5type Store interface {
6 Read(string) ([]byte, error)
7 Save(string, []byte) (error)
8}
2.实现对象接口
假设我们需要将Redis或磁盘作为存储介质,我们需要分别实现Redis与磁盘的存储功能。
FileSystem
1pacakge store
2
3type FileStore struct{
4 /*your codes*/
5}
6
7func (store *FileStore) Read(string) ([]byte, error) {
8 /*your codes*/
9}
10
11func (store *FileStore) Save(string, []byte) (error) {
12 /*your codes*/
13}
14
15// 注意这里要返回 Store 接口,而不是FileStore的指针。
16// 可以保证工厂方法只能调用到对象接口方法,避免封装被破坏。
17func newFileStore() Store {
18 /*your codes*/
19}
Redis
1pacakge store
2
3type RedisStore struct{
4 /*your codes*/
5}
6
7func (store *RedisStore) Read(string) ([]byte, error) {
8 /*your codes*/
9}
10
11func (store *RedisStore) Save(string, []byte) (error) {
12 /*your codes*/
13}
14
15// 注意这里要返回 Store 接口,而不是RedisStore的指针。
16// 可以保证工厂方法只能调用到对象接口方法,避免封装被破坏。
17func newRedisStore() Store {
18 /*your codes*/
19}
3.实现工厂方法
工厂方法是暴露给模块外部使用的,用于创建实例的方法。我们需要将各种类型Store实例的创建过程封装到该方法里面,避免暴露给外部模块。由工厂方法统一提供创建功能。
1pacakge store
2
3type (
4 StoreType int
5)
6
7const (
8 File StorageType = 1 << iota
9 Redis
10)
11
12func NewStore(storeType StoreType) Store {
13 switch storeType {
14 case File:
15 return newFileStore()
16 case Redis:
17 return newRedisStore()
18 default:
19 panic("尚未支持的存储类型!")
20 }
21}
使用
假设我们需要使用Redis作为存储介质,我们只需要在工厂方法中传入store.Redis参数。
1package main
2
3import (
4 "fmt"
5
6 "xxxx/store" // 你的模块地址
7)
8
9func main() {
10 st := store.NewStore(store.Redis)
11
12 // 读取数据
13 data, err := st.Read("/foo")
14 fmt.Println(err, data)
15
16 // 保存数据
17 err = st.Write("/foo", data)
18 fmt.Println(err)
19}
如果现在我们想更换介质为文件系统,我们只需要更换工厂方法中传入的参数为store.File即可完成介质更换。
1// 其他代码不变
2
3// 工厂方法的参数更改为store.File即可。
4st := store.NewStore(store.File)
5
6// 其他代码不变