关于设计模式:Go设计模式之工厂模式

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

  • 简略工厂模式
  • 工厂办法模式
  • 形象工厂模式

这三种模式从上到下逐渐形象,在学习工厂模式之前,须要先明确为什么要应用工厂模式。工厂模式对类的实例化过程进行了形象,可能将软件模块中对象的创立和对象的应用拆散。为了能使得代码构造和逻辑更加清晰,外界对于这些对象只须要晓得他们独特的接口,而不须要晓得外部具体的实现逻辑,使得整个零碎的设计更加合乎繁多指摘准则。工厂模式代替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

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理