文章目录
设计模式:前言
最近在面试的时候频繁被问到“是否有了解过设计模式?简单举几个例子”,发现自己确实缺少对设计模式的了解,因此通过一个新的专栏开始对「设计模式」的相关知识进行学习。
使用的主要开发语言是 Go 语言,参考的主要资料是刘丹冰 AceId 老师的《Easy搞定Golang设计模式》,原文链接如下:https://www.yuque.com/aceld/lfhu8y/rg6nsf。
刘丹冰老师在《Easy搞定Golang设计模式》主要收录了 24 种设计模式,我打算以日更的频率通过这个专栏学习完相关的资源,欢迎讨论。
创造型模式:简单工厂模式
简单工厂模式比较好理解,顾名思义,通过建立一个「工厂」,作为一个抽象的中间层,来负责类实例的创建。
举个例子,假如我们现在的业务代码当中需要创建水果类,如果不通过工厂,那么我们需要知道代码库已经为我们实现了哪些水果的构造函数,需要与每一个具体的水果类型打交道,但是如果我们在中间加入一层「工厂的抽象」,那么我们在业务逻辑当中直接与工厂打交道即可,不需要关心具体的水果实例应该如何创建。
一个使用 Go 语言实现的「简单工厂模式」的 Demo 如下,在该例当中,我们建立了「水果」的接口,我们之后设计的每一个具体的水果类都应该实现水果接口。之后,我们设计一个工厂,它的返回值是「水果」接口。
package main
import "fmt"
// ---------- 抽象层 ----------
// 抽象接口
type Fruit interface {
Show() // 接口的方法
}
// ---------- 基础类模块 ----------
type Apple struct{}
func (apple *Apple) Show() {
fmt.Println("I'm Apple")
}
type Banana struct{}
func (banana *Banana) Show() {
fmt.Println("I'm Banana")
}
type Pear struct{}
func (pear *Pear) Show() {
fmt.Println("I'm Pear")
}
// ---------- 简单工厂模式的工厂模块 ----------
// 简单工厂模式下, 仅有一个工厂实例负责生产水果, 根据传入的类型返回具体对象的指针
type Factory struct{}
func (factory *Factory) CreateFruit(kind string) Fruit {
var fruit Fruit
switch kind {
case "Apple":
fruit = new(Apple)
case "Banana":
fruit = new(Banana)
case "Pear":
fruit = new(Pear)
}
// 简单工厂模式引入"Factory"这个工厂模块将具体的业务逻辑与类实例化解耦
// 但存在的一个问题是"Factory"工厂本身的设计违法了开闭原则, 如果此时我们想新增一个"Peach"类, 那么必须对 Factory 的生产逻辑进行修改
return fruit
}
func main() {
factory := &Factory{}
apple := factory.CreateFruit("Apple")
apple.Show()
banana := factory.CreateFruit("Banana")
banana.Show()
pear := factory.CreateFruit("Pear")
pear.Show()
}
通过代码,我们很直观地了解了「简单工厂模式」的设计思想。
总结一下:
- 简单工厂模式通过「工厂」这个抽象的中间层,来构造我们需要的每一大类实例的「接口」。需要注意的是,对于 Golang 而言,「接口」是鸭子类型,只要某个 struct 实现了 interface 的所有方法,那么这个 struct 就是这个 interface,对应到上例:只要新建的水果类实现了 Show 方法,那么这个水果就是 Fruit 接口。
- 在工厂当中,根据传入的实参,构造具体类型的指针并返回。这是「简单工厂模式」的设计原则,它非常的简单,但是由于简单产生了一个严重的问题,那就是工厂类没有遵循「开闭原则」,如果日后我们想要为水果类加入更多具体的水果,那么就需要修改工厂的代码,比如在 switch 语句块当中多加一个 case。
工厂模式的优缺点:
优点
- 实现了对象创建和使用的分离;
- 不需要记住具体类名,记住参数即可,减少使用者的记忆量。
缺点
- 工厂类职责过重,一旦不能工作,系统会受到影响;
- 增加了系统中类的个数,增加了系统的复杂度和理解难度;
- 违反“开闭原则”,添加新产品需要修改工厂的逻辑,工厂越来越复杂。