创建型 工厂模式
为什么需要工厂模式
一般来说工厂模式下面还有更加细分的类型,简单工厂、工厂方法和抽象工厂。
一般来说工厂模式最主要的作用就是根据输入变量或者配置文件,解析以后根据情况返回不同类型的对象实例。
那我们一般情况下什么时候需要工厂模式呢?
- 创建过程可能会有变更,封装逻辑,使变更对使用者透明
- 允许代码复用,抽象化创建过程
- 封装复杂的创建逻辑
简单工厂
一般来说根据输入参数选择好类型,返回对象就好。根据open closure原则,还是勉强符合的。在需要增添一个类的时候,就是需要继承Gun这个父类,实现创建过程,然后在NewGun里面注册一下即可使用。
go.mod
module factory
go 1.13
factory/simplefactory/simplefactory.go
package simplefactory
type IGun interface {
Fire() string
}
type Gun struct {
name string
}
func NewGun(name string) IGun {
if name == "ak47" {
return newAk47()
}
if name == "maverick" {
return newMaverick()
}
return nil
}
func (g *Gun) Fire() string {
return g.name + " Fire"
}
type ak47 struct {
Gun
}
func newAk47() IGun {
return &ak47{
Gun: Gun{
name: "ak47",
},
}
}
type maverick struct {
Gun
}
func newMaverick() IGun {
return &maverick{
Gun: Gun{
name: "maverick",
},
}
}
factory/simplefactory/simplefactory_test.go
package simplefactory_test
import (
"factory/simplefactory"
"testing"
)
func TestSimpleFactory(t *testing.T) {
ak47 := simplefactory.NewGun("ak47")
maverick := simplefactory.NewGun("maverick")
if ak47.Fire() != "ak47 Fire" {
t.Fatal("Incorrect ak47")
}
if maverick.Fire() != "maverick Fire" {
t.Fatal("Incorrect maverick")
}
}
执行:
go test factory/simplefactory -v
工厂方法模式
这个主要是去掉一个集中的创建方法,把创建factory的过程交还给各个具体实现的类。扩展性更加高一点。当用户要增加新的Gun的时候只需要增加:
- 具体Gun 类
- 具体GunFactory 类
- 在init 函数那里去具体注册
使用场景,需要得到factory创建过程并且做一些复杂的创建配置的时候,可以考虑采用这个设计模型。
factory/factorymethod/factorymethod.go
package factorymethod
type IGun interface {
Fire() string
}
// IGunFactory abstracts out Gun creator. 这个是主要区别
type IGunFactory interface {
NewGun() IGun
}
var cacheFactories map[string]IGunFactory
func init() {
cacheFactories = make(map[string]IGunFactory)
cacheFactories["ak47"] = &ak47Factory{}
cacheFactories["maverick"] = &maverickFactory{}
}
func NewGunFactory(name string) IGunFactory {
return cacheFactories[name]
}
type Gun struct {
name string
}
// we don't need NewGun anymore
func (g *Gun) Fire() string {
return g.name + " Fire"
}
type ak47 struct {
Gun
}
type ak47Factory struct {
}
func (af *ak47Factory) NewGun() IGun {
return &ak47{
Gun: Gun{
name: "ak47",
},
}
}
type maverick struct {
Gun
}
type maverickFactory struct{}
func (mf *maverickFactory) NewGun() IGun {
return &maverick{
Gun: Gun{
name: "maverick",
},
}
}
factory/factorymethod/factorymethod_test.go
package factorymethod_test
import (
"factory/factorymethod"
"testing"
)
func TestFactoryMethod(t *testing.T) {
ak47Factory := factorymethod.NewGunFactory("ak47")
maverickFactory := factorymethod.NewGunFactory("maverick")
ak47 := ak47Factory.NewGun()
maverick := maverickFactory.NewGun()
if ak47.Fire() != "ak47 Fire" {
t.Fatal("Incorrect ak47")
}
if maverick.Fire() != "maverick Fire" {
t.Fatal("Incorrect maverick")
}
}
执行:
go test factory/factorymethod -v