文章目录
- 二、工厂
- 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/*ishou/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
}