文章目录
- 二、工厂
- 2.1 简单工厂
- 2.2 工厂方法
- 2.2.1 目录层级
- 2.2.2 使用方式
- 2.2.3 产品、简单工厂的定义
- 2.2.4 具体工厂的定义
- 2.2.5 具体工厂的实现
- 2.3 抽象工厂
- 2.3.1 目录层级
- 2.3.2 使用工厂
- 2.3.3 定义工厂
- 2.3.4 定义产品
- 2.3.5 json config 的实现
- 2.3.6 yaml config 的具体实现:工厂和产品
二、工厂
https://github.com/ssbandjl/golang-design-pattern/tree/master/00_simple_factory
(图片来源网络,侵删)https://github.com/mohuishou/go-design-pattern/blob/master/02_factory/021_simple_factory/simple_factory.go
分为:简单工厂、工厂方法、抽象工厂。
(图片来源网络,侵删)2.1 简单工厂
因为 go 本身没有构造函数, 通常用 NewXXX 构造, 当返回接口时, 就是简单工厂
可以按如下平铺的目录层级,也可以用分层的目录层级:
02factory/021simple_factory ├── json_parser │ └── json_parser.go ├── simple_factory.go ├── simple_factory_test.go └── yaml_parser └── yaml_parser.go
simple_factory.go 描述了工厂如下:
package simplefactory import ( "godp/02factory/021simple_factory/json_parser" "godp/02factory/021simple_factory/yaml_parser" ) // ConfigParser 是产品的接口 type ConfigParser interface { Parse(b []byte) error } // NewConfigParser 是工厂 // 当构造函数返回接口时就是工厂 // 当在一个工厂, 生产多种产品时, 就是简单工厂 func NewConfigParser(typ string) ConfigParser { switch typ { case "json": return &json_parser.ConfigParser{} case "yaml": return &yaml_parser.ConfigParser{} } return nil }
工厂的测试如下:
package simplefactory import ( "github.com/stretchr/testify/require" "godp/02factory/021simple_factory/json_parser" "godp/02factory/021simple_factory/yaml_parser" "testing" ) func TestNewConfigParser(t *testing.T) { j := NewConfigParser("json") require.Equal(t, j, &json_parser.ConfigParser{}) y := NewConfigParser("yaml") require.Equal(t, y, &yaml_parser.ConfigParser{}) }
json 产品的实现如下:
package json_parser import "encoding/json" // ConfigParser 是 json 产品的具体实现 type ConfigParser struct{} func (p *ConfigParser) Parse(b []byte) error { v := struct{}{} return json.Unmarshal(b, &v) }
yaml 产品的实现如下:
package yaml_parser import "gopkg.in/yaml.v3" // ConfigParser 是 yaml 产品的具体实现 type ConfigParser struct{} func (p *ConfigParser) Parse(b []byte) error { v := struct{}{} return yaml.Unmarshal(b, &v) }
2.2 工厂方法
如果需要每种产品生产的过程比较复杂,不适合放在一个简单工厂中。
则可以把每种产品,都封装一个工厂。
在简单工厂中,根据传入的类型,构造不同的工厂。
这种模式,就是工厂方法模式,也是实践中最常用的。
2.2.1 目录层级
目录层级如下:
02factory/022factory_method ├── factory.go ├── factory_test.go ├── json_factory.go ├── json_parser │ └── json_parser.go ├── yaml_factory.go └── yaml_parser └── yaml_parser.go
2.2.2 使用方式
从 factory_test.go 的单测,可以看出使用方式:
package factory_method import ( "github.com/stretchr/testify/require" "godp/02factory/022factory_method/json_parser" "godp/02factory/022factory_method/yaml_parser" "testing" ) // 链式 func TestCreateJsonParserByChain(t *testing.T) { err := CreateConfigParserFactory(jsonFactoryType).Create().Parse([]byte("{}")) require.NoError(t, err) } func TestCreateYamlParserByChain(t *testing.T) { err := CreateConfigParserFactory(yamlFactoryType).Create().Parse([]byte("{}")) require.NoError(t, err) } // 详细步骤分解 func TestCreateJsonConfigParser(t *testing.T) { jsonFactory := CreateConfigParserFactory(jsonFactoryType) require.Equal(t, jsonFactory, new(jsonConfigParserFactory)) jsonParser := jsonFactory.Create() require.Equal(t, jsonParser, new(json_parser.JsonConfigParser)) err := jsonParser.Parse([]byte("{}")) require.NoError(t, err) } func TestYamlConfigParser(t *testing.T) { f := CreateConfigParserFactory(yamlFactoryType) require.Equal(t, f, new(yamlConfigParserFactory)) parser := f.Create() require.Equal(t, parser, new(yaml_parser.YamlConfigParser)) err := parser.Parse([]byte("{}")) require.NoError(t, err) }
2.2.3 产品、简单工厂的定义
factory.go 定义了产品、工厂:
package factory_method // ConfigParser 是生产出的产品的接口 type ConfigParser interface { Parse(b []byte) error } // ConfigParserFactory 是工厂的接口, 其可以生产产品 type ConfigParserFactory interface { Create() ConfigParser } // FactoryType 是 工厂的类型 type FactoryType string // CreateConfigParserFactory 是向 package 外暴露的方法 // 其用一个简单工厂, 封装工厂方法, 根据数据的工厂类型, 生成对应的工厂(后续可使用对应的工厂, 生产对应的产品) func CreateConfigParserFactory(typ FactoryType) ConfigParserFactory { switch typ { case jsonFactoryType: return new(jsonConfigParserFactory) case yamlFactoryType: return new(yamlConfigParserFactory) } return nil }
2.2.4 具体工厂的定义
工厂方法,会根据 type 返回具体的工厂
Json_factory.go 如下:
package factory_method import "godp/02factory/022factory_method/json_parser" const jsonFactoryType FactoryType = "json" // jsonConfigParserFactory 是 Json 的工厂 type jsonConfigParserFactory struct { } func (f *jsonConfigParserFactory) Create() ConfigParser { return new(json_parser.JsonConfigParser) }
yaml_factory.go 如下:
package factory_method import "godp/02factory/022factory_method/yaml_parser" const yamlFactoryType FactoryType = "yaml" // yamlConfigParserFactory 是生产 yamlConfigParser 的工厂 type yamlConfigParserFactory struct { } func (f *yamlConfigParserFactory) Create() ConfigParser { return new(yaml_parser.YamlConfigParser) }
2.2.5 具体工厂的实现
每个具体实现,都可以创建一个单独的 子 package。即【父 package】定义了产品和简单工厂,【子 package】实现各具体工厂的创建逻辑。
json_parser/json_parser.go 如下:
package json_parser import "encoding/json" type JsonConfigParser struct{} func (j *JsonConfigParser) Parse(b []byte) error { v := struct{}{} return json.Unmarshal(b, &v) }
yaml_parser/yaml_parser.go 如下:
package yaml_parser import "gopkg.in/yaml.v3" type YamlConfigParser struct { } func (y *YamlConfigParser) Parse(b []byte) error { v := struct{}{} return yaml.Unmarshal(b, &v) }
2.3 抽象工厂
之前的【工厂方法】都是指生产一种产品,如果生产多种产品就是抽象工厂。参考:https://refactoringguru.cn/design-patterns/abstract-factory
因为【工厂方法】每增加一种产品,就需要增加一个工厂,这样工厂太多了。所以可以把产品分组,使一个工厂生产多种产品,这就是【抽象工厂】。
例如,如果客户端希望生产服装产品(鞋子、衣服),他们又分为不同厂商的。具体如下:
- Adidas 鞋子
- Adidas 衣服
- Nike 鞋子
- Nike 衣服
则,可以用 Adidas 工厂,生产 Adidas 鞋子和 Adidas 衣服。
再用 Nike 工厂,生产 Nike 鞋子和 Nike 衣服。
因为每种工厂,生产了多件产品(如鞋子、衣服),所以这种模式就是抽象工厂。
2.3.1 目录层级
02factory/023abstract_factory ├── factory.go ├── factory_test.go ├── json_config │ ├── factory.go │ ├── generator.go │ ├── parser.go │ └── readme.md ├── model │ ├── generator.go │ ├── parser.go │ ├── readme.md │ └── type.go └── yaml_config ├── factory.go ├── generator.go ├── parser.go └── readme.md
2.3.2 使用工厂
factory_test.go
package abstract_factory import ( "github.com/stretchr/testify/require" "godp/02factory/023abstract_factory/model" "testing" ) func TestCreateJsonParser(t *testing.T) { NewConfigFactory(model.JsonConfigType).CreateParser().Parse([]byte("{}")) } func TestCreateJsonGenerator(t *testing.T) { v := NewConfigFactory(model.JsonConfigType).CreateGenerator().Generate() require.Nil(t, v) } func TestCreateYamlParser(t *testing.T) { NewConfigFactory(model.YamlConfigType).CreateParser().Parse([]byte("{}")) } func TestCreateYamlGenerator(t *testing.T) { v := NewConfigFactory(model.YamlConfigType).CreateGenerator().Generate() require.Nil(t, v) }
2.3.3 定义工厂
package abstract_factory import ( "godp/02factory/023abstract_factory/json_config" "godp/02factory/023abstract_factory/model" "godp/02factory/023abstract_factory/yaml_config" ) // NewConfigFactory 是对 package 外暴露的接口, 外部的 client 可以从这里获取工厂, 而外部的 client 并不需要了解具体实现 func NewConfigFactory(typ model.ConfigType) ConfigFactory { switch typ { case model.JsonConfigType: return &json_config.Factory{} case model.YamlConfigType: return &yaml_config.Factory{} } return nil } // ConfigFactory 是工厂, 能生产 Config 相关的产品, 如 Parser 或 Generator type ConfigFactory interface { CreateParser() model.Parser CreateGenerator() model.Generator }
2.3.4 定义产品
为了把具体产品放在【子 package】 中,避免循环引用,需要把 产品放在单独的 package 中,如下文的 model package 中。
model/type.go 如下:
package model // ConfigType 是配置的类型, 据此选择对应的工厂 type ConfigType string const ( JsonConfigType ConfigType = "json" YamlConfigType ConfigType = "yaml" )
model/parser.go 定义了第一个产品:
package model // Parser 是第一种产品, 可以 Parse 某文本, 为某格式 type Parser interface { Parse([]byte) }
model/generator.go 定义了第二个产品:
package model // Generator 是第二种产品, 可以按照某格式 Generate 某文本 type Generator interface { Generate() []byte }
2.3.5 json config 的实现
json_config/factory.go 定义了json 的具体工厂实现:
package json_config import ( "godp/02factory/023abstract_factory/model" ) type Factory struct { } func (f *Factory) CreateParser() model.Parser { return &parser{} } func (f *Factory) CreateGenerator() model.Generator { return &generator{} }
json_config/parser.go 定义了 json parser 产品的具体实现:
package json_config // parser 是 json config 的 parser type parser struct { } func (p *parser) Parse([]byte) { }
json_config/generator.go 定义了 json generator 产品的具体实现:
package json_config // generator 是 json config 的 generator type generator struct { } func (g *generator) Generate() []byte { return nil }
2.3.6 yaml config 的具体实现:工厂和产品
yaml_config/factory.go 实现具体 yaml 工厂:
package yaml_config import ( "godp/02factory/023abstract_factory/model" ) type Factory struct{} func (f *Factory) CreateParser() model.Parser { return &parser{} } func (f *Factory) CreateGenerator() model.Generator { return &generator{} }
yaml_config/parser.go 实现 yaml parser 产品:
package yaml_config type parser struct { } func (p *parser) Parse([]byte) { }
yaml_config/generator.go 实现 yaml generator 产品:
package yaml_config type generator struct{} func (g *generator) Generate() []byte { return nil }