工厂模式的定义:
Define an interface for creating an object, but let subclasses decide which class to instantiate. Factory Method lets a class defer instantiation to subclasses.
定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类。 ——《设计模式之禅》
工厂模式分类:
- 一、简单工厂模式
- 二、工厂方法模式
- 三、抽象工厂模式
工厂模式区别:
- 简单工厂 : 使用一个工厂对象用来生产同一等级结构中的任意产品。(不支持拓展增加产品)
- 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
- 抽象工厂 : 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
一、简单工厂模式
package main
import "fmt"
// https://juejin.cn/post/7095581880200167432 用Go语言实现23种设计模式 - 掘金 - juejin
// 参考链接1:https://so.youkuaiyun.com/so/search?q=%E5%B7%A5%E5%8E%82%E6%A8%A1%E5%BC%8F&t=blog&u=weixin_43887447
// 定义一个用于创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类
// 工厂模式中的每个工厂只能生产一种产品,而抽象工厂模式将某些相关、等级结构不同的产品组成了一个“产品族”,然后用一个工厂来统一生产
// 注解:工厂模式只能生产一种产品,而抽象工厂模式可以生产一类产品
// 通用代码
/*
参考链接2: https://blog.youkuaiyun.com/lady_killer9/article/details/119296452
代码逻辑如下:
SimpleFactory
-------------------------
|CreateProduct() Product|
-------------------------
|
|
V
Product
---------------
|Method() void|
---------------
7 ^
/ \
/ \
Product001 Product002
--------------- ---------------
|Method() void| |Method() void|
--------------- ---------------
缺点:当添加一个新的Product003时,需要修改SimpleFactory里面的CreateProduct方法
*/
// 抽象的产品类---接口
type Product interface {
Method() // 抽象方法
}
// 具体产品类001
type Product001 struct{}
// 具体产品类001实现接口的方法
func (p *Product001) Method() {
fmt.Println("我是产品001")
}
// 具体产品类002
type Product002 struct{}
// 具体产品类002实现接口的方法
func (p *Product002) Method() {
fmt.Println("我是产品002")
}
// 现在有一个工厂类,负责生产各种产品
type SimpleFactory struct{}
// 工厂生产各种产品的方法
func (s *SimpleFactory) CreateProduct(t string) Product {
switch t {
case "001":
return &Product001{}
case "002":
return &Product002{}
default:
// 异常处理
return nil
}
}
// 测试简单工厂的方法
func TestSimpleFactory() {
var fm = &SimpleFactory{} // 开了一家工厂
var p1 = fm.CreateProduct("001") // 制造产品001
p1.Method() // 调用产品001的方法
var p2 = fm.CreateProduct("002") // 制造产品002
p2.Method() // 调用产品002的方法
}
// 在主函数中测试
func main() {
TestSimpleFactory()
}
二、工厂方法模式
package main
import "fmt"
// 参考链接:https://blog.youkuaiyun.com/lady_killer9/article/details/119296452
// 工厂方法 : 使用多个工厂对象用来生产同一等级结构中对应的固定产品。(支持拓展增加产品)
// 1. 为了解决第一种简单工厂模式的缺陷,产生了工厂方法模式,把工厂方法再次进行抽象
// 2. 为不同的实现类,提供不同的工厂,通过实现抽象工厂接口类的方法,实现不同工厂获取
// 3. 业务实现类的不同实例,调用的时候,通过判断,使用不同的工厂(在简单工厂模式基础上)
/*
参考链接2: https://blog.youkuaiyun.com/lady_killer9/article/details/119296452
代码逻辑如下:
Foods
-----------------------
| Make() void |
-----------------------
7 ^
/ \
/ \
Vegetable Meat
--------------- ---------------
| Make() void| | Make() void|
--------------- ---------------
^ ^
. .
. FoodsFactory .
. ------------------------- .
. | GetFood() Foods | .
. ------------------------- .
. 7 ^ .
. / \ .
. / \ .
VegetableFactory MeatFactory
----------------- -----------------
|GetFood() Foods| |GetFood() Foods|
----------------- -----------------
优点:添加食物时,添加一个类和对应的具体工厂方法即可,不需要修改源代码
缺点:在添加新产品时,需要编写新的具体产品类,而且还要提供与之对应的具体工厂类,系统中类的个数将成对增加;
在一定程度上增加了系统的复杂度,有更多的类需要编译和运行,会给系统带来一些额外的开销。
*/
// 抽象的 食物类 接口
type Foods interface {
Make()
}
// 具体的 蔬菜类
type Vegetable struct{}
// 蔬菜类 实现食物类的Make方法
func (v *Vegetable) Make() {
fmt.Println("我可以制作蔬菜类食物.")
}
// 具体的 肉类
type Meat struct{}
// 肉类 实现食物类的Make方法
func (m *Meat) Make() {
fmt.Println("我可以制作肉类食物.")
}
// 不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂
// 故而需要一个抽象的工厂类,定义GetFood方法
type FoodsFactory interface {
GetFood()
}
// 因为上面写了2种具体的食物类,所以需要实现2个具体的工厂类
// 1. 蔬菜类制作工厂
type VegetableFactory struct{}
// 2. 实现抽象工厂的 GetFood方法
func (vf *VegetableFactory) GetFood() Foods {
return &Vegetable{}
}
// 3. 肉类制作工厂
type MeatFactory struct{}
// 4. 实现抽象工厂的 GetFood方法
func (mf *MeatFactory) GetFood() Foods {
return &Meat{}
}
func TestFactoryMethod() {
fmt.Println("测试工厂方法模式:")
var vf = &VegetableFactory{} // 开了一家制作蔬菜的工厂
var vege = vf.GetFood() // 从工厂中获取一个要制作的蔬菜食物对象
vege.Make() // 调用Make方法,制作食物
var mf = &MeatFactory{} // 开了一家制作肉类的工厂
var meat = mf.GetFood() // 从工厂中获取一个要制作的肉类食物对象
meat.Make() // 调用Make方法,制作食物
}
// 在主函数main中测试
func main(){
TestFactoryMethod()
}
三、抽象工厂模式
源自菜鸟教程:
抽象工厂模式(Abstract Factory Pattern)是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。
在抽象工厂模式中,接口是负责创建一个相关对象的工厂,不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象
package main
// 使用多个工厂对象用来生产不同产品族的全部产品。(不支持拓展增加产品;支持增加产品族)
/*
参考链接:https://blog.youkuaiyun.com/lvyibin890/article/details/107659348
场景描述:
现在有一个超级工厂,它负责创建实现了抽象工厂接口的工厂;
抽象工厂接口一共有三个方法,分别对应创建了三个产品族,分别是手机产品族,Ipad产品族与智能音箱产品族;
一共有两个工厂实现了这个抽象工厂接口,分别是华为工厂和小米工厂, 其中华为工厂不生产智能音箱产品族;
优点: 当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。
缺点: 产品族扩展十分困难,当需要增加一个产品族的时候,抽象工厂需要多提供一个接口创建此产品族的产品,而具体的工厂也需要增加方法实现该接口
*/
import "fmt"
// 先定义几种工厂的类型
const (
Huawei = iota
Xiaomi
Unsupported
)
// -----------------------------------------------------如下为三个产品族 手机、Ipad以及智能音箱-----------------------------------------------------
// 手机接口
type Cellphone interface {
Call()
}
// Ipad接口
type Ipad interface {
Play()
}
// 智能音箱接口
type SmartSoundBox interface {
Listen()
}
// -----------------------------------------------------如下为抽象工厂接口,需要能够生产 手机、Ipad 以及 智能音箱-----------------------------------------------------
type AbstractFactory interface {
CreateCellphone() Cellphone
CreateIpad() Ipad
CreateSmartSoundBox() SmartSoundBox
}
// -----------------------------------------------------如下为两个具体工厂 华为工厂和小米工厂-----------------------------------------------------
// 华为工厂:1. 实现 产品族的接口 手机接口 和 Ipad接口
type HuaweiCellphone struct{}
func (*HuaweiCellphone) Call() {
fmt.Println("I made a call on my HuaweiCellphone")
}
// 华为Ipad
type HuaweiIpad struct{}
func (*HuaweiIpad) Play() {
fmt.Println("I am playing with HuaweiIpad")
}
// 华为工厂:2. 实现了抽象工厂的两个接口
type HuaweiFactory struct{}
func (*HuaweiFactory) CreateCellphone() Cellphone {
return &HuaweiCellphone{}
}
func (*HuaweiFactory) CreateIpad() Ipad {
return &HuaweiIpad{}
}
// 华为工厂不生产智能音箱
func (*HuaweiFactory) CreateSmartSoundBox() SmartSoundBox {
fmt.Println("Huawei not produce SmartSoundBox")
return nil
}
// 小米工厂:1. 实现 产品族的接口 手机接口 、 Ipad接口 和智能音箱接口
type XiaomiCellphone struct{} // 小米手机,实现了手机接口
func (*XiaomiCellphone) Call() {
fmt.Println("I made a call on my XiaomiCellphone")
}
// 小米Ipad
type XiaomiIpad struct{}
func (*XiaomiIpad) Play() {
fmt.Println("I am playing with XiaomiIpad")
}
// 小米智能音箱
type XiaomiSmartSoundBox struct{}
func (*XiaomiSmartSoundBox) Listen() {
fmt.Println("I am listening with XiaomiSmartSoundBox")
}
// 小米工厂:2. 实现了抽象工厂的两个接口
type XiaomiFactory struct{}
func (*XiaomiFactory) CreateCellphone() Cellphone {
return &XiaomiCellphone{}
}
func (*XiaomiFactory) CreateIpad() Ipad {
return &XiaomiIpad{}
}
func (*XiaomiFactory) CreateSmartSoundBox() SmartSoundBox {
return &XiaomiSmartSoundBox{}
}
// -----------------------------------------------------如下为超级工厂接口,创建一个具体的 抽象工厂-----------------------------------------------------
type HyperFactory interface {
CreateFactory(t int) AbstractFactory
}
// 超级工厂实例
type HypeFactoryImpl struct{}
// 根据给定的类型参数创建 对应的抽象工厂
func (*HypeFactoryImpl) CreateFactory(t int) AbstractFactory {
switch t {
case Huawei:
fmt.Println("-----Creat Huawei Factory-----")
return &HuaweiFactory{}
case Xiaomi:
fmt.Println("-----Creat Xiaomi Factory-----")
return &XiaomiFactory{}
default:
return nil
}
}
func TestAbstractFactory() {
// 创建一个超级工厂,用于生产工厂
var hf HyperFactory = &HypeFactoryImpl{}
// 创建具体的工厂
var factory AbstractFactory
// 1. 具体的华为工厂
factory = hf.CreateFactory(Huawei)
factory.CreateCellphone().Call()
factory.CreateIpad().Play()
factory.CreateSmartSoundBox()
// 2. 具体的小米工厂
factory = hf.CreateFactory(Xiaomi)
factory.CreateCellphone().Call()
factory.CreateIpad().Play()
factory.CreateSmartSoundBox().Listen()
}
func main(){
TestAbstractFactory()
}