【创造型模式】简单工厂模式

发布于:2025-05-19 ⋅ 阅读:(14) ⋅ 点赞:(0)

设计模式:前言

最近在面试的时候频繁被问到“是否有了解过设计模式?简单举几个例子”,发现自己确实缺少对设计模式的了解,因此通过一个新的专栏开始对「设计模式」的相关知识进行学习。

使用的主要开发语言是 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。

工厂模式的优缺点:
优点

  • 实现了对象创建和使用的分离;
  • 不需要记住具体类名,记住参数即可,减少使用者的记忆量。

缺点

  • 工厂类职责过重,一旦不能工作,系统会受到影响;
  • 增加了系统中类的个数,增加了系统的复杂度和理解难度;
  • 违反“开闭原则”,添加新产品需要修改工厂的逻辑,工厂越来越复杂。

网站公告

今日签到

点亮在社区的每一天
去签到