• go设计模式之工厂方法模式


    工厂方法模式

    什么是工厂方法模式

    工厂方法模式是一种创建型设计模式,它定义了一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化推迟到其子类。

    这个接口就是工厂接口,子类就是具体工厂类,而需要创建的对象就是产品对象。客户端代码只需要调用工厂接口的方法,而无需关心具体的产品对象是如何创建的。

    用于创建对象的过程中将实例化的逻辑封装在一个工厂方法中。

    把被创建的对象称为“产品”,把创建产品的对象称为“工厂”。

    在 Go 语言中,工厂方法模式经常被用于对象的创建和初始化。

    工厂方法模式的主要优点有:

    • 用户只需要知道具体工厂的名称就可得到所要的产品,无须知道产品的具体创建过程(对创建过程复杂的对象很有作用);

    • 在系统增加新的产品时只需要添加具体产品类和对应的具体工厂类,无须对原工厂进行任何修改,满足开闭原则;

    其缺点是:每增加一个产品就要增加一个具体产品类和一个对应的具体工厂类,这增加了系统的复杂度。

    角色

    工厂方法模式包含四个主要角色:

    • 抽象产品类(Product)
    • 具体产品类(ConcreteProduct)
    • 抽象工厂接口(Factory)
    • 具体工厂类(ConcreteFactory)

    抽象产品类定义了产品的接口。

    具体产品类实现了具体的产品逻辑。

    抽象工厂类定义了创建产品的接口。

    具体工厂类实现了具体的产品创建逻辑。

    工厂方法代码

    工厂方法模式举例

    场景:

    创建狗子的案例:
    创建狗子的接口工厂(接口MakeDogs)
    创建狗子具体工厂(实现上面的接口)
    狗子接口(sleep()、run())
    泰迪、柴犬(具体的狗子)

    抽象产品类:

    type IDog interface {
    	Sleep()
    	Run()
    }
    
    • 1
    • 2
    • 3
    • 4

    具体产品类:

    柴犬:

    // 柴犬
    type ChaiDog struct {
    }
    
    func (c ChaiDog) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (c ChaiDog) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    泰迪:

    // 泰迪
    type Teddy struct {
    }
    
    func (t Teddy) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (t Teddy) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    抽象工厂类(接口工厂):

    创建狗子的抽象接口

    type IDogFactory interface {
    	MakeDogs(dogType string) IDog
    }
    
    • 1
    • 2
    • 3

    具体工厂类:

    type DogFactory struct {
    }
    
    // 工厂方法,这是一个特殊的方法,用来创建不同的狗子
    func (d DogFactory) MakeDogs(dogType string) IDog {
    	if dogType == "teddy" {
    		return &Teddy{}
    	}
    	if dogType == "chaidog" {
    		return &ChaiDog{}
    	}
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    场景类:

    func main() {
    	factory := &DogFactory{}
        // 传入teddy,产生对应的狗子
    	t := factory.MakeDogs("teddy")
    	t.Sleep()
    	t.Run()
        // 传入chaidog,产生对应的狗子
    	c := factory.MakeDogs("chaidog")
    	c.Sleep()
    	c.Run()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    简单工厂方法代码

    缩小为简单工厂模式。

    一个模块仅需要一个工厂类,没有必要把它实例化出来。java使用静态方法就可以了。

    场景:

    创建狗子的案例:

    没有创建狗子的接口工厂

    创建狗子的具体工厂(MakeDogs())
    狗子接口(sleep()、run())
    泰迪、柴犬(具体的狗子)

    抽象产品类:

    type IDog interface {
    	Sleep()
    	Run()
    }
    
    • 1
    • 2
    • 3
    • 4

    具体产品类:

    柴犬:

    // 柴犬
    type ChaiDog struct {
    }
    
    func (c ChaiDog) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (c ChaiDog) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    泰迪:

    // 泰迪
    type Teddy struct {
    }
    
    func (t Teddy) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (t Teddy) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    抽象工厂类(接口工厂):

    去掉。

    具体工厂类:

    // 工厂方法,这是一个特殊的方法,用来创建不同的狗子
    func MakeDogs(dogType string) IDog {
    	if dogType == "teddy" {
    		return &Teddy{}
    	}
    	if dogType == "chaidog" {
    		return &ChaiDog{}
    	}
    	return nil
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    场景类:

    func main() {
    	t := ex.MakeDogs("teddy")
        t.Sleep()
    	t.Run()
    	c := ex.MakeDogs("chaidog")
    	c.Sleep()
    	c.Run()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    工厂方法代码3

    升级为多个工厂类。

    假如有1个产品类有5个具体实现,每个实现类的初始化方法都不相同,如果写在一个工厂方法中,会导致这个方法巨大无比。

    为每一个产品定义一个创建者。

    创建狗子的案例:

    创建狗子的接口工厂(MakeDogs())

    创建泰迪狗子的具体工厂(实现上面的接口)

    创建泰迪柴犬的具体工厂(实现上面的接口)

    狗子接口(sleep()、run())
    泰迪、柴犬(具体的狗子)

    接口工厂类:

    type IDogFactory interface {
    	// 无需再传递参数了
    	MakeDogs() IDog
    }
    
    • 1
    • 2
    • 3
    • 4

    抽象产品类:

    type IDog interface {
    	Sleep()
    	Run()
    }
    
    • 1
    • 2
    • 3
    • 4

    具体产品类:

    柴犬:

    // 柴犬
    type ChaiDog struct {
    }
    
    func (c ChaiDog) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (c ChaiDog) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    泰迪:

    // 泰迪
    type Teddy struct {
    }
    
    func (t Teddy) Sleep() {
    	fmt.Println("睡觉")
    }
    
    func (t Teddy) Run() {
    	fmt.Println("奔跑")
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    具体工厂:

    // 创建柴犬的具体工厂
    type ChaiDogFactory struct {
    }
    
    func (c ChaiDogFactory) MakeDogs() IDog {
    	return &ChaiDog{}
    }
    
    // 创建柴犬的具体工厂
    type ChaiDogFactory struct {
    }
    
    func (c ChaiDogFactory) MakeDogs() IDog {
    	return &ChaiDog{}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    场景类:

    func main() {
    	f1 := &example.TeddyFactory{}
    	dog1 := f1.MakeDogs()
    	dog1.Sleep()
    	dog1.Run()
    	f2 := &example.ChaiDogFactory{}
    	dog2 := f2.MakeDogs()
    	dog2.Sleep()
    	dog2.Run()
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    设计模式之原型模式--超越实例化的魔法,从复制到创造的无限可能
    Python 笔记01 (变量和面向对象编程)
    如何用一个插件解决 Serverless 灰度发布难题?
    使用Spring WebFlux和Spring Cloud的反应式微服务
    Visual Studio Code调试和发布ASP.NET Core Web应用
    ABB机器人切割铣削钻孔自动化加工应用
    动物园规则怪谈【逻辑】
    Java:Java 反射API简介
    Python语法--for、while循环操作
    深度解析Shopee虾皮高效选品逻辑方法
  • 原文地址:https://blog.csdn.net/shulu/article/details/138164882