工厂模式属于结构型模式,可以细分为三种模式:

  • 简单工厂模式
  • 工厂方法模式
  • 抽象工厂模式

这三种模式从上到下逐步抽象,在学习工厂模式之前,需要先明白为什么要使用工厂模式。工厂模式对类的实例化过程进行了抽象,能够将软件模块中对象的创建和对象的使用分离。为了能使得代码结构和逻辑更加清晰,外界对于这些对象只需要知道他们共同的接口,而不需要知道内部具体的实现逻辑,使得整个系统的设计更加符合单一指责原则。工厂模式代替new初始化实例对象,这样做的好处是封装了更多的实现细节,可以对对象的生命周期进行更好的管理。

一、简单工厂模式

简单工厂模式是三种模式中最简单的模式、也是最常用的一种工厂模式。简单工厂模式时有一个工厂来决定创建哪一种实例对象。代码如下:

package factory

import "fmt"

type Phone interface {
    Show()
}

// ----------实现层逻辑------------
type Apple struct {
    Phone
}

func (a *Apple) Show() {
    fmt.Println("苹果手机")
}

type Huawei struct {
    Phone
}

func (h *Huawei) Show() {
    fmt.Println("华为手机")
}

type Xiaomi struct {
    Phone
}

func (x *Xiaomi) Show() {
    fmt.Println("小米手机")
}

// ----------工厂模块------------
type Factory struct {
}

func (f *Factory) createFruit(kind string) Phone {
    var phone Phone

    switch kind {
    case "apple":
        phone = new(Apple)
    case "huawei":
        phone = new(Huawei)
    case "xiaomi":
        phone = new(Xiaomi)
    }

    return phone
}

测试用例

package factory

import "testing"

func TestFactory(t *testing.T) {
    factory := new(Factory)

    apple := factory.createFruit("apple")
    apple.Show()

    huawei := factory.createFruit("huawei")
    huawei.Show()

    xiaomi := factory.createFruit("xiaomi")
    xiaomi.Show()
}

执行结果

=== RUN   TestFactory
苹果手机
华为手机
小米手机
--- PASS: TestFactory (2.11s)
PASS

Debugger finished with the exit code 0

上边的程序中,定义了三个结构体,结构体都实现了Phone接口,创建一个工厂模块,工厂模块提供初始化程序,根据传入的参数决定生产苹果、华为还是小米手机。这样在测试用例中,只需要初始化一次工厂,工厂对象创建实例对象即可,创建实例的操作定义在createFactory中即可。
简单工厂模式的优缺点:

  • 优点:调用者只需要知道参数和方法名称即可创建对象,无需知道内部实现细节,大大方便了调用者的使用。
  • 缺点:缺点很明显--扩展性太差。简单工厂的核心是工厂模块,工厂模块中根据传递的参数来决定创建哪一种对象,很适合对象类型少且类型固定场景,如果要添加其他的对象除了创建新的结构体、实现接口,还需要修改工厂模块,添加新的分支才可以,这样严重违背了开闭原则,对扩展开放、对修改封闭。

    二、工厂方法模式

    工厂方法模式是对简单工厂模式的进一步抽象,工厂方法模式一定程度上解决了简单工厂模式扩展性不好的问题。具体代码如下:

    package method
    
    import "fmt"
    
    // ----------抽象层------------
    type Phone interface {
      Show()
    }
    
    type AbstractFactory interface {
      ProductPhone() Phone // 一定要返回Phone接口
    }
    
    // ----------实现层逻辑------------
    type Apple struct {
      Phone
    }
    
    func (a *Apple) Show() {
      fmt.Println("苹果手机")
    }
    
    type Huawei struct {
      Phone
    }
    
    func (h *Huawei) Show() {
      fmt.Println("华为手机")
    }
    
    type Xiaomi struct {
      Phone
    }
    
    func (x *Xiaomi) Show() {
      fmt.Println("小米手机")
    }
    
    // ----------具体工厂逻辑------------
    type AppleFactory struct{}
    
    func (a *AppleFactory) ProductPhone() Phone {
      var phone Phone
      phone = new(Apple)
    
      return phone
    }
    
    type HuaweiFactory struct{}
    
    func (h *HuaweiFactory) ProductPhone() Phone {
      var phone Phone
      phone = new(Huawei)
    
      return phone
    }
    
    type XiaomiFactory struct{}
    
    func (a *XiaomiFactory) ProductPhone() Phone {
      var phone Phone
      phone = new(Xiaomi)
    
      return phone
    }
    
    
    // 测试程序
    package method
    
    import "testing"
    
    func TestAppleFactory_ProductPhone(t *testing.T) {
      // 苹果手机工厂
      var appleFac AbstractFactory
      appleFac = new(AppleFactory)
      var apple Phone
      apple = appleFac.ProductPhone()
      apple.Show()
    
      // 华为手机工厂
      var huaweiFac AbstractFactory
      huaweiFac = new(HuaweiFactory)
      var huawei Phone
      huawei = huaweiFac.ProductPhone()
      huawei.Show()
    
      // 小米手机工厂
      var xiaomiFac AbstractFactory
      xiaomiFac = new(XiaomiFactory)
      var xiaomi Phone
      xiaomi = xiaomiFac.ProductPhone()
      xiaomi.Show()
    }
    

    运行结果

    === RUN   TestAppleFactory_ProductPhone
    苹果手机
    华为手机
    小米手机
    --- PASS: TestAppleFactory_ProductPhone (0.00s)
    PASS
    
    Process finished with the exit code 0

    工厂方法模式有几个核心模块:

  • 抽象层: 抽象出对外提供需要被调用的接口。
  • 具体工厂层:这一层为创建具体对象的层级,每一中对象都对应一个专门的工厂来生产。
  • 实现逻辑层:具体的实现,创建对象后的业务逻辑封装在这一层级。

工厂方法模式的优缺点:

  • 优点:工厂方法模式把简单工厂的单一工厂改为多个工厂,原来是父类生产所有类型的对象,现在是把生产对象的逻辑下放都具体的子类,由子类来控制。这样的话,如果有新的类型进来,只需要在实现逻辑层添加一个结构体,在具体工厂层创建对应的工厂即可,可以根据需要添加,而无需修改原有的代码,这样就很好的遵循了开闭原则,实现了解藕。
  • 缺点:添加一个类型就需要创建两个结构体,如果添加的类型很多,就会大大增加系统复杂性,也不易理解。

三、抽象工厂模式

抽象工厂模式针对产品镞是符合开闭原则的,但对产品等级结构不是符合开闭原则的,适合产品镞比较多且产品等级结构很稳定的场景下使用。代码如下:
定义抽象逻辑:

package factory

// ----------抽象逻辑------------
type Phone interface {
    ShowPhone()
}

type Computer interface {
    ShowComputer()
}

type HeadPhone interface {
    ShowHeadPhone()
}

type AbstractFactory interface {
    ProductPhone() Phone
    ProductComputer() Computer
    ProductHeadPhone() HeadPhone
}

定义华为产品镞实现层:

package factory

import "fmt"

// ----------实现层逻辑------------
type HuaweiPhone struct{}

func (h *HuaweiPhone) ShowPhone() {
    fmt.Println("华为手机")
}

type HuaweiComputer struct {
}

func (h *HuaweiComputer) ShowComputer() {
    fmt.Println("华为电脑")
}

type HuaweiHeadPhone struct {
}

func (h *HuaweiHeadPhone) ShowHeadPhone() {
    fmt.Println("华为耳机")
}

type HuaweiFactory struct {
}

func (h *HuaweiFactory) ProductPhone() Phone {
    var phone Phone
    phone = new(HuaweiPhone)

    return phone
}

func (h *HuaweiFactory) ProductComputer() Computer {
    var computer Computer
    computer = new(HuaweiComputer)
    return computer
}

func (h *HuaweiFactory) ProductHeadPhone() HeadPhone {
    var headPhone HeadPhone
    headPhone = new(HuaweiHeadPhone)
    return headPhone
}

定义苹果产品镞实现层:

package factory

import "fmt"

// ----------实现层逻辑------------
type ApplePhone struct{}

func (h *ApplePhone) ShowPhone() {
    fmt.Println("苹果手机")
}

type AppleComputer struct {
}

func (h *AppleComputer) ShowComputer() {
    fmt.Println("苹果电脑")
}

type AppleHeadPhone struct {
}

func (h *AppleHeadPhone) ShowHeadPhone() {
    fmt.Println("苹果耳机")
}

type AppleFactory struct {
}

func (h *AppleFactory) ProductPhone() Phone {
    var phone Phone
    phone = new(ApplePhone)

    return phone
}

func (h *AppleFactory) ProductComputer() Computer {
    var computer Computer
    computer = new(AppleComputer)
    return computer
}

func (h *AppleFactory) ProductHeadPhone() HeadPhone {
    var headPhone HeadPhone
    headPhone = new(AppleHeadPhone)
    return headPhone
}

定义小米产品镞实现层:

package factory

import "fmt"

// ----------实现层逻辑------------
type XiaomiPhone struct{}

func (h *XiaomiPhone) ShowPhone() {
    fmt.Println("小米手机")
}

type XiaomiComputer struct {
}

func (h *XiaomiComputer) ShowComputer() {
    fmt.Println("小米电脑")
}

type XiaomiHeadPhone struct {
}

func (h *XiaomiHeadPhone) ShowHeadPhone() {
    fmt.Println("小米耳机")
}

type XiaomiFactory struct {
}

func (h *XiaomiFactory) ProductPhone() Phone {
    var phone Phone
    phone = new(XiaomiPhone)

    return phone
}

func (h *XiaomiFactory) ProductComputer() Computer {
    var computer Computer
    computer = new(XiaomiComputer)
    return computer
}

func (h *XiaomiFactory) ProductHeadPhone() HeadPhone {
    var headPhone HeadPhone
    headPhone = new(XiaomiHeadPhone)
    return headPhone
}

测试程序:

package factory

import "testing"

func TestFactory(t *testing.T) {
    // 华为
    var hf AbstractFactory
    hf = new(HuaweiFactory)
    hf.ProductPhone().ShowPhone()
    hf.ProductHeadPhone().ShowHeadPhone()
    hf.ProductComputer().ShowComputer()

    // 苹果
    var af AbstractFactory
    af = new(AppleFactory)
    af.ProductPhone().ShowPhone()
    af.ProductHeadPhone().ShowHeadPhone()
    af.ProductComputer().ShowComputer()

    // 小米
    var xf AbstractFactory
    xf = new(AppleFactory)
    xf.ProductPhone().ShowPhone()
    xf.ProductHeadPhone().ShowHeadPhone()
    xf.ProductComputer().ShowComputer()
}

运行结果:

=== RUN   TestFactory
华为手机
华为耳机
华为电脑
苹果手机
苹果耳机
苹果电脑
苹果手机
苹果耳机
苹果电脑
--- PASS: TestFactory (0.00s)
PASS

Process finished with the exit code 0

TimeWtr
1 声望0 粉丝