1.前提:
需要先了解简单工厂的来龙去脉,下面附上简单工厂的代码
type animal interface{}
type dog struct{}
type cat struct{}
type duck struct{}
func NewExample(name string) animal {
switch name {
case "dog":
return &dog{}
case "cat":
return &cat{}
case "duck":
return &duck{}
}
return nil
}
type breeder struct{}
func (b *breeder) NewExample(name string) animal {
switch name {
case "dog":
return &dog{}
case "cat":
return &cat{}
case "duck":
return &duck{}
}
return nil
}
2.抽象工厂
分析一下简单工厂,我们可以发现,想要使用 NewExample 去得到各种的实例化
那你必须是一个breeder【饲养员】结构体才行
因为它们之间形成了绑定的,那是不是可以抽象一下【饲养员】
比如:老师可以是饲养员,学生也可以是饲养员,等等,这样一来就可以放开 NewExample 的适用范围
package main
import "fmt"
type animal interface{}
type dog struct{}
type cat struct{}
type duck struct{}
type breeder interface {
NewExample(name string) animal
}
type teacher struct{}
// 由于把工厂函数提到了接口里面,所以这种工厂称为抽象工厂
func (b *teacher) NewExample(name string) animal {
switch name {
case "dog":
return &dog{}
case "cat":
return &cat{}
case "duck":
return &duck{}
}
return nil
}
// 可以发现,出现接口以后,还能通过重新写实现函数的逻辑来限制住不同人取实例化的种类
type student struct{}
func (s *student) NewExample(name string) animal {
switch name {
case "dog":
return &dog{}
}
return nil
}
// 抽象工厂是在简单工厂的基础上把工厂函数写入了接口
// 把工厂类抽象成了接口
func main() {
b := new(teacher)
a := b.NewExample("dog")
fmt.Printf("%#v", a)
}
总结:
想扩大函数的绑定范围,就把结构体提为接口,函数纳入接口属性
之前:
type breeder struct{}
func (b *breeder) NewExample(name string) animal {}
之后:
type breeder interface {
NewExample(name string) animal
}