## 工厂模式
#### 1.简单工厂
```go
//定义两个生成动物的工厂,一个生成Dog,一个生成Cat
type Cat struct{}
type Dog struct{}
//定义一个接口,为了代码简单,这里我定义了一个空接口,这样Dog,Cat就不用实现任何方法
type Animal interface{}
//简单工厂方法,用于生成具体动物
func Create(animalType string) Animal {
var animal Animal
switch animalType {
case "cat":
animal = &Cat{}
case "dog":
animal = &Dog{}
}
return animal
}
```
以上就是一个简单工厂模式
使用如下:
```go
cat := Create("cat")
dog := Create("dog")
```
一切看上去好像很完美,但是当我们需要新加入一种动物(即新添加一个工厂)时,我们还是需要修改两处地方,修改如下
```go
//第一处修改,新建一个动物结构(如duck)
type Duck struct{}
//第二处修改
func Create(animalType string) Animal {
var animal Animal
switch animalType {
case "cat":
animal = &Cat{}
case "dog":
animal = &Dog{}
case "duck": //++++此处为新增逻辑
animal = &Duck{}
}
return animal
}
```
修改Create方法并不是明智之举,很明显违背了设计模式的开闭原则,那有什么方法加以改善???
由于本人也是刚接触go,在这里提出以下想法,写得不好,或者有什么问题,希望各位看官指正,经过修改代码如下
#### 2.工厂方法
```go
//定义两个生成动物的工厂,一个生成Dog,一个生成Cat
type Cat struct{}
type Dog struct{}
//定义一个接口
type Animal interface{}
//Cat的构造函数
func CreateCat() Animal{
retrun &Cat{}
}
//Dog的构造函数
func CreateDog() Animal{
retrun &Dog{}
}
```
```go
//定义一个工厂结构
//结构里面只有一个类型为[string]func() Animal的map,它主要是用来存放各种动物的”构造函数“
type Factry struct {
animals map[string]func() Animal
}
```
为了描述方便我们可以把func() Animal定义为CreateFn
```go
type CreateFn func() Animal
//于是Factry可以改写为
type Factry struct{
animals map[string]CreateFn
}
```
定义一个newFactry方法,方法主要用于生成Factry实列,并且构建animals,目的是为了构建一个描述动物关键字(如:”cat"代表Cate,"dog"代表Dog)与各动物”构造函数“的映射
```go
func newFactry() *Factry {
return &Factry{
animals: map[string]CreateFn{
"dog": CreateDog,//把"dog"关键字映射到构造函数CreateDog
"cat": CreateCat,
},
}
}
```
至此主要逻辑就已经完成了,剩下怎么创建具体动物这一步了,我们给Factry结构体添加一个Create方法方法,如下:
```go
func (f *Factry) Create(name string) Animal {
//name为关键字,通过关键字,我们可以从animals找到对应的构造函数
return f.animals[name]()
}
```
### 大功告成
至此工厂方法已经好了,那怎么使用列?如下:
```go
fac := newFactry() //新建一个工厂
dog := fac.Create("dog")//新建一个dog
cat := fac.Create("cat") //新建一个cat
```
## 总结:通过以上改造,我们解决了简单工厂添加新工厂存在的问题,即需要添加新分支:
```go
case "duck": //++++此处为新增逻辑
animal = &Duck{}
```
### 因为,我们统一把分支管理交给了工厂结构体里的animals map[string]CreateFn来管理,这样添加新动物时,我们只需要专心写我们的动物结构就可以了,写好后在animals 添加对应关系即可,
### 通过这样的改造,我们虽然解决了修改case分支的问题,但又多了新问题,需要维护animals ,看上去好像也没有什么改善,但对于大型复杂的软件工程来说,维护animals,应该比维护case分支好,通过维护animals,我们把创建具体动物的权限交还给了动物的“构造函数”本身,使得动物结构更加合理,而不是把构建交给case
以上就是我的愚见,希望大家参考改进,有什么好的想法,请大家留意,共同进步!!!
有疑问加站长微信联系(非本文作者))