Golang设计模式-创建型-简单工厂

来源:互联网 发布:电商java 编辑:程序博客网 时间:2024/06/06 00:47

1 引例

李雷喜欢上了韩梅梅,他知道韩梅梅喜欢吃汉堡,于是就想买汉堡给她吃,但李雷不确定韩梅梅喜欢的是肯德基的汉堡还是麦当劳的汉堡,怎样帮助他呢?
最直观和最简单的实现就是if+else:

if prefer == "KFC" {    CreateKfcHamburger()} else if prefer == "McDonalds" {    CreateMcdonaldsHamburger()}

这个实现的问题是客户端关注了产品(汉堡)创建的全过程,且当扩展产品种类时需要修改客户端代码,违反了开放-封闭原则(对增加开放,对修改封闭)。
那么有没有更好的实现呢?

2 简单工厂

2.1 定义

简单工厂通过定义一个工厂类,并提供创建产品的方法,将客户端从创建具体产品的尴尬局面中摆脱出来,客户端只需要告知产品类型即可,产品的具体创建由工厂完成。

简单工厂-定义

2.2 简单工厂三要素

  • 产品: 客户端需要的产品
  • 工厂: 生产产品的工厂
  • 客户端: 消费产品的客户

以引例的汉堡工厂为例,产品即为汉堡,这个是一个抽象类型,根据产品类型的不同,我们分别定义两个具体产品,即肯德基的汉堡和麦当劳的汉堡:

type Hamburger interface {    Deliver()}type KfcHamburger struct{}func (h KfcHamburger) Deliver() {    fmt.Println("This is a hamburger from KFC.")}type McdonaldsHamburger struct{}func (h McdonaldsHamburger) Deliver() {    fmt.Println("This is a hamburger from McDonalds.")}

汉堡工厂则根据需要生产指定类型的汉堡:

type HamburgerFactory struct{}func (f HamburgerFactory) CreateHamburger(prefer string) Hamburger {    switch prefer {    case "KFC":        return new(KfcHamburger)    case "McDonalds":        return new(McdonaldsHamburger)    default:        return nil    }}

于是,客户端再也不关注产品的具体创建过程了,而是告诉工厂“我需要什么,你就给我生产什么”:

func main() {    prefer := getPreferHamburger()    factory := new(creational.HamburgerFactory)    hamburger := factory.CreateHamburger(prefer)    if hamburger == nil {        fmt.Printf("%s not supported yet.\n", prefer)        os.Exit(1)    }    hamburger.Deliver()}

李雷作为客户,只需要获取韩梅梅喜欢的汉堡类型,然后让工厂生产就可以了:

$ ./simple_factory.bin -prefer KFCThis is a hamburger from KFC.$ ./simple_factory.bin -prefer McDonaldsThis is a hamburger from McDonalds.

使用类图表示如下:

简单工厂-汉堡

2.3 简单工厂的优缺点

  • 优点
    • 客户端不关注产品的创建过程,避免客户端逻辑的复杂;
    • 利于扩展新产品,且无需修改客户端代码。
  • 缺点
    • 当产品种类较多时,工厂逻辑会变得非常复杂;
    • 虽然新增产品时不需要修改客户端实现,但仍然需要对工厂逻辑做调整,实际也不完全符合“开放-封闭”原则。

完整代码: 简单工厂

阅读全文
0 0