概念
简单工厂模式(Simple Factory Pattern)
工厂方法模式(Factory Method):定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类
抽象工厂模式:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类
要解决的问题/用途
- 当创建逻辑比较复杂,是一个“大工程”的时候,我们就考虑使用工厂模式
- 封装对象的创建过程,将对象的创建和使用相分离
- 代码中存在
if-else
分支判断,动态地根据不同的类型创建不同的对象。将这一大坨if-else
创建对象的代码抽离出来,放到工厂类中.
- 尽管我们不需要根据不同的类型创建不同的对象,但是,单个对象本身的创建过程比较复杂,
比如要组合其他类对象,做各种初始化操作。在这种情况下,我们也可以考虑使用工厂模式,将对象的创建过程封装到工厂类中
如何实现
1,简单工厂模式(Simple Factory Pattern)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
package main
import "errors"
var rcpFactory1 *RuleConfigParserFactory1
func Load1(configFormat string) (RuleConfig, error) { parser, err := rcpFactory1.createParser(configFormat) if err != nil { return nil, err } var text string return parser.Parse(text)
}
type RuleConfigParserFactory1 struct { }
func (r *RuleConfigParserFactory1) createParser(configFormat string) (IRuleConfigParser, error) { var parser IRuleConfigParser if configFormat == "json" { parser = &JsonRuleConfigParser{} } else if configFormat == "xml" { parser = &XmlRuleConfigParser{} } else if configFormat == "yml" { parser = &YamlRuleConfigParser{} } else { return nil, errors.New("configFormat invalid") } return parser, nil }
type IRuleConfigParser interface { Parse(text string) (RuleConfig, error) }
type JsonRuleConfigParser struct { }
func (j *JsonRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type YamlRuleConfigParser struct { }
func (y *YamlRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type XmlRuleConfigParser struct { }
func (x *XmlRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type RuleConfig interface { }
|
还有一种简单工厂模式的实现,和单例模式相结合
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| package main
import ( "errors" "strings" )
var rcpFactory2 = &RuleConfigParserFactory2{ cacheParsers: map[string]IRuleConfigParser{ "json": &JsonRuleConfigParser{}, "xml": &XmlRuleConfigParser{}, "yaml": &YamlRuleConfigParser{}, }, }
func Load2(configFormat string) (RuleConfig, error) { parser, err := rcpFactory2.createParser(configFormat) if err != nil { return nil, err } var text string return parser.Parse(text)
}
type RuleConfigParserFactory2 struct { cacheParsers map[string]IRuleConfigParser }
func (r *RuleConfigParserFactory2) createParser(configFormat string) (IRuleConfigParser, error) { configFormat = strings.ToLower(configFormat) parser, ok := r.cacheParsers[configFormat] if !ok { return nil, errors.New("configFormat invalid") } return parser, nil }
|
简单工厂模式总结:尽管简单工厂模式的代码实现中,有多处if分支判断逻辑,违背开闭原则,
但权衡扩展性和可读性,这样的代码实现在大多数情况下(比如,不需要频繁地添加parser,也没有太多的parser)
是没有问题的
2,工厂方法(Factory Method)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
| package main
import "errors"
var rcpFactory1 *RuleConfigParserFactory1
func Load1(configFormat string) (RuleConfig, error) { factory, err := rcpFactory1.getFactory(configFormat) if err != nil { return nil, err } parser := factory.CreateParser() var text string return parser.Parse(text)
}
type RuleConfigParserFactory1 struct { }
func (r *RuleConfigParserFactory1) getFactory(configFormat string) (IRuleConfigParserFactory, error) { var factory RuleConfigParseFactory if configFormat == "json" { factory = &JsonRuleConfigParserFactory{} } else if configFormat == "xml" { factory = &XmlRuleConfigParserFactory{} } else if configFormat == "yml" { factory = &YamlRuleConfigParserFactory{} } else { return nil, errors.New("configFormat invalid") } return factory, nil }
type IRuleConfigParserFactory interface { CreateParser() IRuleConfigParser }
type JsonRuleConfigParserFactory struct { }
func (j *JsonRuleConfigParserFactory) CreateParser() IRuleConfigParser { return &JsonRuleConfigParser{} }
type YamlRuleConfigParserFactory struct { }
func (j *YamlRuleConfigParserFactory) CreateParser() IRuleConfigParser { return &YamlRuleConfigParser{} }
type XmlRuleConfigParserFactory struct { }
func (j *XmlRuleConfigParserFactory) CreateParser() IRuleConfigParser { return &XmlRuleConfigParser{} }
type IRuleConfigParser interface { Parse(text string) (RuleConfig, error) }
type JsonRuleConfigParser struct { }
func (j *JsonRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type YamlRuleConfigParser struct { }
func (y *YamlRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type XmlRuleConfigParser struct { }
func (x *XmlRuleConfigParser) Parse(text string) (RuleConfig, error) { panic("implement me") }
type RuleConfig interface { }
|
考虑到工厂类只包含方法,不包含成员变量,所以完全可以复用,于是有了工厂方法模式的另外一种实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| package main
import ( "errors" "strings" )
var rcpFactory2 = &RuleConfigParserFactory2{ m: map[string]RuleConfigParseFactory{ "json": &JsonRuleConfigParserFactory{}, "xml": &XmlRuleConfigParserFactory{}, "yaml": &YamlRuleConfigParserFactory{}, }, }
func Load2(configFormat string) (RuleConfig, error) { factory, err := rcpFactory2.getFactory(configFormat) if err != nil { return nil, err } parser := factory.CreateParser() var text string return parser.Parse(text)
}
type RuleConfigParserFactory2 struct { m map[string]RuleConfigParseFactory }
func (r *RuleConfigParserFactory2) getFactory(configFormat string) (RuleConfigParseFactory, error) { configFormat = strings.ToLower(configFormat) factory, ok := r.m[configFormat] if !ok { return nil, errors.New("configFormat invalid") } return factory, nil }
|
工厂方法模式总结:对于规则配置文件解析这个应用场景来说,工厂模式需要额外创建诸多Factory类,
也会增加代码的复杂性,而且,每个Factory类只是做简单的new操作,功能非常单薄(只有一行代码),
也没必要设计成独立的类,所以,在这个应用场景下,简单工厂模式简单好用,比工厂方法模式更加合适
抽象工厂(Abstract Factory)
一个factory接口创建多个parser
1 2 3 4 5 6 7 8
|
type IconfigParserFactory interface { CreateRuleParser() CreateSystemParser() }
|