假设现在有这么一个需求:
就是我给一个动物种类,这个函数就可以给我返回这个动物种类的实例化
大概就是这样的
type dog struct {}
type cat struct {}
type duck struct{}
func NewExample(name string){
switch name{
case "dog":
return &dog{}
case "cat":
return &cat{}
case "duck":
return &duck{}
}
}
//显然这样还不够,因为在函数的返回那里还没有写返回类型限制
//那么什么类型才能同时限制住这三种结构体 a.三者的共同父类 b.接口
//a方案显然不行,因为 dog,cat,duck 的属性里面并没有任何的继承结构体出现,更不用说公共的父类
所以现在就只能考虑 b 方案:
而要想满足一个结构体就是接口,那就必须保证结构体是实现了接口的
于是乎问题就办成了,现在需要抽象出一个接口,然后让 dog,cat,duck 都去实现它
type animal interface{}
type dog struct{}
type cat struct{}
type duck struct{}
// 当然这里的 animal 接口是一个空接口,所以任何一个结构体都是默认实现过了
// 如果是 animal 接口里面但凡有一个函数eg:print,那么比如dog结构体想要实现,那就得
// 一点不偷懒的写,func (d *dog)print(){}
func NewExample(name string) animal {
switch name {
case "dog":
return &dog{}
case "cat":
return &cat{}
case "duck":
return &duck{}
}
return nil
}
当然更多的时候,也会给 NewExample 再绑定一个结构体,这也就形成了本节的 简单工厂
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
}
func main() {
b := new(breeder)
a := b.NewExample("dog")
fmt.Printf("%#v", a)
}
你可能很不理解:
废了这么大的周折就为了一个实例化 ???
我要用的话,直接比如说,d:=&dog{}不是代码少很多,多省事儿
是的,这样直接用代码是很少
但是它对业务层代码【就是放业务代码的go文件】形成了一个入侵
因为业务层代码只关心 1.拿到实例化 2.用实例化处理逻辑,3....
它根本不想关心拿到一个 dog 的实例化,要写一个 &dog{} 这种玩意
它觉得这种玩意就不应该出现在业务层
无论后来增加多少种的实例化case分支,对于业务层代码来说,它无所谓,
因为它心里拿到一个dog的实例化代码 NewExample("dog") 始终没变就行
这也就形成了一种业务层代码与实例化函数的【低耦合】关系
所以就考虑把所有获得实例化的操作放进一个 NewExample 的函数里面,然后把这个函数就放在【业务代码go文件】之外的文件就行,然后这个 NewExample 就是一个简单工厂的角色