设计模式-工厂方法模式(Go实现)
Posted lady_killer9
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了设计模式-工厂方法模式(Go实现)相关的知识,希望对你有一定的参考价值。
工厂方法模式
定义一个用于创建对象的接口,让子类决定将哪一个类实例化。不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。
工厂方法模式四要素:
- 工厂接口。工厂接口是工厂方法模式的核心,与调用者直接交互用来提供产品。在实际编程中,有时候也会使用一个抽象类来作为与调用者交互的接口,其本质上是一样的。
- 工厂实现。在编程中,工厂实现决定如何实例化产品,是实现扩展的途径,需要有多少种产品,就需要有多少个具体的工厂实现。
- 产品接口。产品接口的主要目的是定义产品的规范,所有的产品实现都必须遵循产品接口定义的规范。产品接口是调用者最为关心的,产品接口定义的优劣直接决定了调用者代码的稳定性。同样,产品接口也可以用抽象类来代替,但要注意最好不要违反里氏替换原则。
- 产品实现。实现产品接口的具体类,决定了产品在客户端中的具体行为。
需求
快餐店的食物,目前有汉堡,粥,需要向顾客展示价格。
修改前
简单工厂设计
缺点
添加食物时需要修改工厂类FoodsFactory的方法GetFood
代码
package SimpleFactory
import (
"fmt"
)
type Foods interface {
Display()
}
type Hamburger struct {
price int
}
func (h Hamburger) Display() {
fmt.Println("I'm Hamburger, price is ",h.price)
}
type Porridge struct {
price int
}
func (p Porridge) Display() {
fmt.Println("I'm Porridge, price is ",p.price)
}
type FoodsFactory struct {
}
func (f FoodsFactory)GetFood(name string) Foods {
switch name {
case "hamburger":
return & Hamburger{price: 10}
case "porridge":
return &Porridge{price: 8}
default:
return nil
}
}
修改后
工厂方法设计
优点
添加食物时,添加一个类和对应的具体工厂方法即可,不需要修改源代码
代码
package FactoryMethod
import (
"fmt"
)
type Foods interface {
Display()
}
type Hamburger struct {
price int
}
func (h Hamburger) Display() {
fmt.Println("I'm Hamburger, price is ",h.price)
}
type Porridge struct {
price int
}
func (p Porridge) Display() {
fmt.Println("I'm Porridge, price is ",p.price)
}
type FoodsFactory interface {
GetFood()
}
type HamburgerFactory struct {
}
func (h HamburgerFactory)GetFood() Foods {
return & Hamburger{price: 10}
}
type PorridgeFactory struct {
}
func (p PorridgeFactory)GetFood() Foods {
return &Porridge{price: 8}
}
测试
测试代码
package FactoryMethod
import "testing"
func TestMethod(t *testing.T) {
h := HamburgerFactory{}
ham := h.GetFood()
ham.Display()
p := PorridgeFactory{}
por := p.GetFood()
por.Display()
}
结果
=== RUN TestMethod
I’m Hamburger, price is 10
I’m Porridge, price is 8
— PASS: TestMethod (0.00s)
PASS
总结
适用场景
- 客户端不知道它所需要的对象的类。在工厂方法模式中,客户端不需要知道具体产品类的类名,只需要知道所对应的工厂即可,具体的产品对象由具体工厂类创建,可将具体工厂类的类名存储在配置文件或数据库中。
- 抽象工厂类通过其子类来指定创建哪个对象。在工厂方法模式中,对于抽象工厂类只需要提供一个创建产品的接口,而由其子类来确定具体要创建的对象,利用面向对象的多态性和里氏代换原则,在程序运行时,子类对象将覆盖父类对象,从而使得系统更容易扩展。
优点
-
无须知道具体产品类的类名。工厂方法用来创建客户所需要的产品,同时还向客户隐藏了哪种具体产品类将被实例化这一细节,用户只需要关心所需产品对应的工厂,无须关心创建细节。
-
基于工厂角色和产品角色的多态性设计是工厂方法模式的关键。它能够让工厂可以自主确定创建何种产品对象,而如何创建这个对象的细节则完全封装在具体工厂内部。工厂方法模式之所以又被称为多态工厂模式,就正是因为所有的具体工厂类都具有同一抽象父类。
-
在系统中加入新产品时,无须修改抽象工厂和抽象产品提供的接口,无须修改客户端,也无须修改其他的具体工厂和具体产品,而只要添加一个具体工厂和具体产品就可以了,这样,系统的可扩展性也就变得非常好,完全符合“开闭原则”。
缺点
- 在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加,在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
- 由于考虑到系统的可扩展性,需要引入抽象层,在客户端代码中均使用抽象层进行定义,增加了系统的抽象性和理解难度,且在实现时可能需要用到反射等技术,增加了系统的实现难度。
参考
以上是关于设计模式-工厂方法模式(Go实现)的主要内容,如果未能解决你的问题,请参考以下文章