工厂方法是一种创建型模式。主要分为两种
1.简单工厂
- 基本定义
简单工厂需要三个部分,工厂结构体、产品接口、产品结构体。
- 示例代码
//动物工厂结构体
type AnimalFactory struct {
}
//动物工厂生产方法
func (m *AnimalFactory) Generate(name string ) IAnimal{
switch name {
case "dog":
return &Dog{}
case "cat":
return &Cat{}
default:
panic("不存在的动物")
}
}
//动物接口
type IAnimal interface {
Say()
}
//动物结构体-狗
type Dog struct {
}
func (m *Dog) Say(){
fmt.Println("dog say")
}
//动物结构体-猫
type Cat struct {
}
func (m *Cat) Say(){
fmt.Println("cat say")
}
func main(){
animalFactory:=AnimalFactory{}
animal:=animalFactory.Generate("dog")
animal.Say()
}
- 优缺点
优点:逻辑简单
缺点:创建代码过于耦合,创建部分没做到依赖倒置
适用场景:业务耦合处,有组件变化时需要改动相关代码的地方。
2.工厂方法
- 基本定义
工厂方法包括工厂接口、工厂结构体、产品接口、产品结构体
- 示例代码
type IAnimalFactory interface {
Create() IAnimal
}
//动物
type IAnimal interface {
Say()
}
type Dog struct {
}
func (m *Dog) Say() {
fmt.Println("dog run")
}
type Cat struct {
}
func (m *Cat) Say() {
fmt.Println("cat run")
}
type DogFactory struct {
}
func (m *DogFactory) Create() IAnimal {
return &Dog{}
}
type CatFactory struct {
}
func (m *CatFactory) Create() IAnimal {
return &Cat{}
}
func main() {
factory := CatFactory{}
animal := factory.Create()
animal.Say()
}
- 优缺点
优点:
符合“开闭”原则,具有很强的的扩展性、弹性和可维护性。修改时只需要添加对应的工厂类即可
使用了依赖倒置原则,依赖抽象而不是具体,使用(客户)和实现(具体类)松耦合
客户只需要知道所需产品的具体工厂,而无须知道具体工厂的创建产品的过程,甚至不需要知道具体产品的类名。
缺点:
每增加一个产品时,都需要一个具体类和一个具体创建者,使得类的个数成倍增加,导致系统类数目过多,复杂性增加
对简单工厂,增加功能修改的是工厂类;对工厂方法,增加功能修改的是产品类。
适用场景:
底层基础库,比如框架中设计了对注册中心的拓展支持。只需要在框架中定义注册中心的工厂接口和注册中心接口。
然后需要拓展任何组件(比如etcd)作为注册中心时,只需要实现对应的工厂接口和注册中心接口就可以将其提供给框架底层使用。
对工厂方法的简单使用能简单理解工厂模式的两种使用场景。即在底层框架设计时,应该保证依赖倒置,即框架使用的是抽象的接口而不是具体的结构体。所以应该使用工厂方法。 在业务中简单使用时,因为本身业务代码就是耦合的,所以可以使用简单工厂去实现它。