介绍
工厂方法模式要求定义一个方法,所有对象都通过该方法创建,子类可以重写该方法更改创建对象的属性。
组成
- 抽象工厂角色: 这是工厂方法模式的核心,它与应用程序无关。是具体工厂角色必须实现的接口或者必须继承的父类
- 具体工厂角色:它含有和具体业务逻辑有关的代码。
- 抽象产品角色:它是具体产品继承的父类或者是实现的接口。
- 具体产品角色:具体工厂角色所创建的对象就是此角色的实例。
示例介绍
我们以造抢为例,这里我们定义一个枪支工厂gunFactory
,用来制造枪支。这里我们的工厂可以制造两种枪支ak47
、m16
,每只枪都有名字(name)和火力值(power)属性。
我们可以为每把枪单独设值名字和火力值,并且可以获取枪的名字和火力值
代码示例
抽象工厂角色:枪拥有的接口
type Gun interface {
setName(name string)
setPower(power int)
getName() string
getPower() int
}
抽象产品角色:枪的通用设置
type gun struct {
name string
power int
}
func (g *gun) setName(name string) {
g.name = name
}
func (g *gun) setPower(power int) {
g.power = power
}
func (g *gun) getName() string {
return g.name
}
func (g *gun) getPower() int {
return g.power
}
具体工厂角色:建造工厂
func gunFactory(ty string) Gun {
switch ty {
case "ak47":
return newAk47()
case "m16":
return newM16()
}
return nil
}
具体产品角色:ak47
type ak47 struct {
gun
}
func newAk47() Gun {
return &ak47{
gun: gun{
name: "ak47",
power: 3,
},
}
}
具体产品角色:m16
type m16 struct {
gun
}
func newM16() Gun {
return &m16{
gun: gun{
name: "m16",
power: 4,
},
}
}
至此我们的枪支工厂已经组建完成,可以生产两种类型的枪支,并且能获取和设置枪的火力和名字
接下来我们开始生产枪支,并调节火力吧!
func Test_gunFactory(t *testing.T) {
ak47 := gunFactory("ak47")
name := ak47.getName()
power := ak47.getPower()
assert.Equal(t, name, "ak47")
assert.Equal(t, power, 3)
ak47.setPower(5)
power = ak47.getPower()
assert.Equal(t, power, 5)
m16 := gunFactory("m16")
assert.Equal(t, m16.getPower(), 4)
}