golang设计模式--抽象工厂

161 阅读1分钟

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  
}