设计模式是面向对象软件的设计经验,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。每一种设计模式系统的命名、解释和评价了面向对象中一个重要的和重复出现的设计。
创建模式是用来帮助我们创建对象的,具体有如下几种:
追 MM 少不了请吃饭了,麦当劳的鸡翅和肯德基的鸡翅都是 MM 爱吃的东西,虽然口味有所不同,但不管你带 MM 去麦当劳或肯德基,只管向服务员说「来四个鸡翅」就行了。麦当劳和肯德基就是生产鸡翅的 Factory 工厂模式:客户类和工厂类分开。
消费者任何时候需要某种产品,只需向工厂请求即可。消费者无须修改就可以接纳新产品。缺点是当产品修改时,工厂类也要做相应的修改。如:如何创建及如何向客户端提供。
简单工厂模式(Simple Factory Pattern):又称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。在简单工厂模式中,可以根据参数的不同返回不同类的实例。
工厂类含有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以免除直接创建产品对象的责任,而仅仅“消费”产品;简单工厂模式通过这种做法实现了对责任的分割,它提供了专门的工厂类用于创建对象。 客户端无须知道所创建的具体产品类的类名,只需要知道具体产品类所对应的参数即可,对于一些复杂的类名,通过简单工厂模式可以减少使用者的记忆量。 通过引入配置文件,可以在不修改任何客户端代码的情况下更换和增加新的具体产品类,在一定程度上提高了系统的灵活性。
由于工厂类集中了所有产品创建逻辑,一旦不能正常工作,整个系统都要受到影响。 使用简单工厂模式将会增加系统中类的个数,在一定程序上增加了系统的复杂度和理解难度。 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。 简单工厂模式由于使用了静态工厂方法,造成工厂角色无法形成基于继承的等级结构。
由于 Go 本身是没有构造函数的,一般而言我们采用 NewName
的方式创建对象/接口,当它返回的是接口的时候,其实就是简单工厂模式
package factory
// IRuleConfigParser IRuleConfigParser
type IRuleConfigParser interface {
Parse(data []byte)
}
// jsonRuleConfigParser jsonRuleConfigParser
type jsonRuleConfigParser struct {
}
// Parse Parse
func (J jsonRuleConfigParser) Parse(data []byte) {
panic("implement me")
}
// yamlRuleConfigParser yamlRuleConfigParser
type yamlRuleConfigParser struct {
}
// Parse Parse
func (Y yamlRuleConfigParser) Parse(data []byte) {
panic("implement me")
}
// NewIRuleConfigParser NewIRuleConfigParser
func NewIRuleConfigParser(t string) IRuleConfigParser {
switch t {
case "json":
return jsonRuleConfigParser{
}
case "yaml":
return yamlRuleConfigParser{
}
}
return nil
}
package factory
import (
"reflect"
"testing"
)
func TestNewIRuleConfigParser(t *testing.T) {
type args struct {
t string
}
tests := []struct {
name string
args args
want IRuleConfigParser
}{
{
name: "json",
args: args{
t: "json"},
want: jsonRuleConfigParser{
},
},
{
name: "yaml",
args: args{
t: "yaml"},
want: yamlRuleConfigParser{
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewIRuleConfigParser(tt.args.t); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewIRuleConfigParser() = %v, want %v", got, tt.want)
}
})
}
}
在工厂方法模式中,我们执行单个函数,传入一个参数(提供信息表明我们想要什么),但 并不要求知道任何关于对象如何实现以及对象来自哪里的细节
创建对象需要大量重复的代码 客户端(应用层)不依赖于产品实例,如何被创建、实现等细节 一个类通过其子类来指定创建哪个对象
用户只需要关心所需产品对应的工厂,无须关心创建细节 加入新产品符合开闭原则,提高可扩展性
在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到DOM、反射等技术,增加了系统的实现难度。
当对象的创建逻辑比较复杂,不只是简单的 new
一下就可以,而是要组合其他类对象,做各种初始化操作的时候,推荐使用工厂方法模式,将复杂的创建逻辑拆分到多个工厂类中,让每个工厂类都不至于过于复杂
// IRuleConfigParserFactory 工厂方法接口
type IRuleConfigParserFactory interface {
CreateParser() IRuleConfigParser
}
// yamlRuleConfigParserFactory yamlRuleConfigParser 的工厂类
type yamlRuleConfigParserFactory struct {
}
// CreateParser CreateParser
func (y yamlRuleConfigParserFactory) CreateParser() IRuleConfigParser {
return yamlRuleConfigParser{
}
}
// jsonRuleConfigParserFactory jsonRuleConfigParser 的工厂类
type jsonRuleConfigParserFactory struct {
}
// CreateParser CreateParser
func (j jsonRuleConfigParserFactory) CreateParser() IRuleConfigParser {
return jsonRuleConfigParser{
}
}
// NewIRuleConfigParserFactory 用一个简单工厂封装工厂方法
func NewIRuleConfigParserFactory(t string) IRuleConfigParserFactory {
switch t {
case "json":
return jsonRuleConfigParserFactory{
}
case "yaml":
return yamlRuleConfigParserFactory{
}
}
return nil
}
package factory
import (
"reflect"
"testing"
)
func TestNewIRuleConfigParserFactory(t *testing.T) {
type args struct {
t string
}
tests := []struct {
name string
args args
want IRuleConfigParserFactory
}{
{
name: "json",
args: args{
t: "json"},
want: jsonRuleConfigParserFactory{
},
},
{
name: "yaml",
args: args{
t: "yaml"},
want: yamlRuleConfigParserFactory{
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := NewIRuleConfigParserFactory(tt.args.t); !reflect.DeepEqual(got, tt.want) {
t.Errorf("NewIRuleConfigParserFactory() = %v, want %v", got, tt.want)
}
})
}
}
抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,属于对象创建型模式。一个抽象工厂是一些工厂方法的(逻辑)集合,其中每一个工厂方法负责生成不同的对象。
请 MM 去麦当劳吃汉堡,不同的 MM 有不同的口味,要每个都记住是一件烦人的事情,我一般采用 Factory Method 模式,带着 MM 到服务员那儿,说「要一个汉堡」,具体要什么样的汉堡呢,让 MM 直接跟服务员说就行了。
工厂方法模式:核心工厂类不再负责所有产品的创建,而是将具体创建的工作交给子类去做,成为一个抽象工厂角色,仅负责给出具体工厂类必须实现的接口,而不接触哪一个产品类应当被实例化这种细节。
使用工厂模式还是抽象工厂模式?
通常先从简单的工厂模式开始,后面发现应用程序需要许多的工厂方法,且将这些工厂方法组合起来创建一系列的对象是有意义的,这样的话