Go设计模式--简单工厂模式

参考:https://github.com/mohuishou/go-design-pattern/tree/master/02_factory

设计模式简单介绍:

设计模式(Design pattern) 代表了最佳的实践,通常被有经验的面相对象的软件开发人员所采用。设计模式是软件开发人员在软件开发过程中面临的一般问题的解决方案。这些解决方案是众多软件开发人员经过相当长的一段时间的试验和错误总结出来的。


画图理解:

image.png

适用场景

  • 工厂类负责创建的对象比较少,不会造成工厂方法中的业务逻辑太过复杂
  • 客户端只知道传入工厂类的参数,并不关心如何创建对象

优点:

  • 简单工厂模式实现了对象创建和使用的分离。工厂类包含必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例,客户端可以仅仅使用产品。

缺点:

  • 由于工厂类集中了所有产品的创建逻辑,职责过重,一旦不能正常工作,整个系统都要受到影响。
  • 使用简单工厂模式势必会增加系统中类的个数,增加了系统的复杂度和理解难度。
  • 系统扩展困难,一旦添加新产品就不得不修改工厂逻辑,在产品类型较多时,有可能造成工厂逻辑过于复杂,不利于系统的扩展和维护。

简单工厂模式理解一

  • 理解
    Newxxx 的函数返回接口时就是简单工厂模式,也就是说Go语言的一般推荐做法就是简单工厂。

  • demo

package main

import "fmt"

// API is interface 
type API interface {
  Say(name string) string
}

func NewAPI(t int) API {
  if t == 1 {
    return &hiAPI{}
}
if t == 2 {
    return &helloAPI{}
}
}


type hiAPI struct{}

func (*hiAPI) Say(name string) string {
    return fmt.Sprintf("Hi, %s", name)
}

// HelloAPI is another API implement
type helloAPI struct{}

// Say hello to name
func (*helloAPI) Say(name string) string {
    return fmt.Sprintf("Hello, %s", name)
}
  • test.go
package main

import "testing"

func TestType1(t *testing.T) {
   api := NewAPI(1)
   s := api.Say("Tom")
   if s != "Hi, Tom" {
       t.Fatal("Type1 test fail")
   }
}

func TestType2(t *testing.T) {
   api := NewAPI(2)
   s := api.Say("Tom")
   if s != "Hello, Tom" {
       t.Fatal("Type2 test fail")
   }
}


简单工厂模式理解二

比如我们有一个生产IPhone的工厂(工厂构造函数),那么我们告诉工厂我们想要的IPhone的型号(iPhone的版本号以函数参数的形式传入),让其为我们生产(返回实例)。


type IPhone interface {
    LoginQQ()
}
 
type IPhone7 struct{}
 
func (p *IPhone7) LoginQQ() {
    fmt.Println("正在使用 IPhone7 登陆QQ")
}
 
type IPhone13 struct{}
 
func (p *IPhone13) LoginQQ() {
    fmt.Println("正在使用 IPhone13 登陆QQ")
}
 
//IPhone生产工厂,根据要求版本号生成新的IPhone
func NewIphone(version int) IPhone {
    switch version {
    case 7:
        return &IPhone7{}
    case 13:
        return &IPhone13{}
    default:
        //该工厂不支持该版本号的IPhone生产,所以返回空
        return nil
    }
}
 
func main() {
    //我想要最新款,😄😄
    iphone := NewIphone(13)
    if iphone == nil {
        fmt.Println("创建新IPhone失败")
        return
    }
 
    iphone.LoginQQ()
}


代码例子3:


package main

import "fmt"

// 水果工厂类实现
type Fruit interface {
    grant() // 种植
    pick()  // 收获
}

// 水果子类 -- 苹果
type Apple struct {
    name string
}

func (*Apple) grant() {
    fmt.Println("种植苹果成功...")
}

func (*Apple) pick() {
    fmt.Println("采摘苹果成功...")
}

// 水果子类--橘子
type Orange struct {
    name string
}

func (*Orange) grant() {
    fmt.Println("种植橘子成功...")
}

func (*Orange) pick() {
    fmt.Println("采摘橘子成功...")
}

// 工厂类,负责生产具体的水果. (多态)
func NewFruit(t int) Fruit {
    switch t {
    case 1:
        return &Apple{}
    case 2:
        return &Orange{}
    }
    return nil
}

func main() {
    apple := NewFruit(1)
    apple.grant()
    apple.pick()

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容