当前位置: 首页 > article >正文

【创造型模式】工厂方法模式

文章目录

  • 工厂方法模式
    • 工厂方法模式当中的角色和职责
    • 工厂方法模式的实现
    • 工厂方法模式的优缺点

工厂方法模式

在这里插入图片描述
今天我们继续学习一例创造型设计模式——工厂方法模式。参考的主要资料是刘丹冰老师的《Easy 搞定 Golang 设计模式》。

工厂方法模式当中的角色和职责

简单来说,工厂方法模式 = 简单工厂模式 + “开闭原则”。工厂方法模式当中具有以下几个角色:

  • 抽象工厂角色:工厂方法模式的核心,任何工厂类都必须实现这个接口。「与“简单工厂模式”相比,工厂方法模式进一步对“工厂”这个角色进行了抽象,而在“简单工厂模式”当中仅使用一个工厂来负责所有结构实例的创建」
  • 具体工厂角色:即具体的工厂,它是抽象工厂的实现,负责是厉害产品对象。
  • 抽象产品角色:工厂方法模式所创建的所有对象的父类,它负责描述所有实例共有的公共接口。
  • 具体产品角色:工厂方法模式所创建的具体实例。

工厂方法模式的实现

基于上述工厂方法模式的角色和职责,现在我们使用 Go 来实现一个工厂方法模式的 Demo。下例是对昨天学习的“简单工厂模式”的升级,新建了一个抽象工厂,并为每一个水果实现了具体的水果工厂,这样就可以做到“开闭原则”,即“针对每一种新的水果,我不再需要修改工厂的代码,而是直接新写一个具体工厂并生产相应的水果即可”。

package mainimport "fmt"// ---------- 抽象层 ----------
// 水果类(抽象接口)
type Fruit interface {Show()
}// 工厂类(抽象接口)
type AbstractFactory interface {CreateFruit() Fruit // 后续的具体工厂需要实现 CreateFruit 方法
}// ---------- 基础类模块 ----------
type Apple struct {Fruit
}func (apple *Apple) Show() {fmt.Println("I'm Apple")
}type Banana struct {Fruit
}func (banana *Banana) Show() {fmt.Println("I'm Banana")
}type Pear struct {Fruit
}func (pear *Pear) Show() {fmt.Println("I'm Pear")
}// ---------- 工厂模块 ----------
// 具体苹果工厂
type AppleFactory struct {AbstractFactory
}func (af *AppleFactory) CreateFruit() Fruit {return &Apple{}
}type BananaFactory struct {AbstractFactory
}func (bf *BananaFactory) CreateFruit() Fruit {return &Banana{}
}type PearFactory struct {AbstractFactory
}func (pf *PearFactory) CreateFruit() Fruit {return &Pear{}
}func main() {// 新建一个具体的苹果工厂appleFactory := &AppleFactory{}// 通过具体苹果工厂生产苹果实例apple := appleFactory.CreateFruit()apple.Show() // 调用苹果方法// 如法炮制, 新建香蕉和梨工厂并生产水果bananaFactory := &BananaFactory{}banana := bananaFactory.CreateFruit()banana.Show()pearFactory := &PearFactory{}pear := pearFactory.CreateFruit()pear.Show()
}

需要注意的是,main 函数的实现我与刘丹冰老师给出的 Demo 实现不太一样。原文当中通过var新建了appleFac这个AbstractFactory变量,并使用new对工厂进行初始化。简而言之就是在业务逻辑层面向抽象层开发,只与工厂耦合,并且只与抽象的工厂和抽象的水果类耦合,遵循了面向抽象层接口编程的原则。一个按照上述原则重新实现的main函数如下:

func main() {var appleFac AbstractFactoryappleFac = &AppleFactory{}var apple Fruitapple = appleFac.CreateFruit()apple.Show()var bananaFac AbstractFactorybananaFac = &BananaFactory{}var banana Fruitbanana = bananaFac.CreateFruit()banana.Show()var pearFac AbstractFactorypearFac = &PearFactory{}var pear Fruitpear = pearFac.CreateFruit()pear.Show()
}

为了进一步体现工厂方法模式的开闭原则,接下来我们尝试在原有代码的基础上添加一个新产品的生产,比如“山东苹果”,具体添加的代码如下:

/*... ... ...*/type ShanDongApple struct {Fruit
}func (sda *ShanDongApple) Show() {fmt.Println("I'm Apple from ShanDong")
}/*... ... ...*/type ShanDongAppleFactory struct {AbstractFactory
}func (sdaf *ShanDongAppleFactory) CreateFruit() Fruit {return &ShanDongApple{}
}/*... ... ...*/func main() {/*... ... ...*/var shandongAppleFac AbstractFactoryshandongAppleFac = &ShanDongAppleFactory{}var shandongApple FruitshandongApple = shandongAppleFac.CreateFruit()shandongApple.Show()
}

可以看到,新增的基本类“山东苹果”和“山东苹果工厂”没有改动之前的任何代码,完全符合开闭原则思想。新增的功能不会影响到之前已有系统的稳定性。与之相比,如果采用简单工厂模式,那么针对新增的“山东苹果”产品,必须修改工厂,添加与“山东苹果”相关的生产逻辑,这样就会改动已有的业务逻辑,不够好。

工厂方法模式的优缺点

优点

  • 不需要记住具体类名,甚至连具体参数都不需要记忆;
  • 实现了对象创建和使用的分离;
  • 系统的可拓展性非常好,无需改动接口和原类;
  • 新产品的创建符合开闭原则。

缺点

  • 会增加系统中类的个数,复杂度增加,需要更长的时间理解;
  • 增加了系统的抽象性和理解难度。

适用场景

  • 客户端不知道它需要的对象的类。
  • 抽象工厂类通过其子类来指定创建哪个对象。
http://www.lryc.cn/news/2385023.html

相关文章:

  • 【MySQL】使用文件进行交互
  • # 大模型的本地部署与应用:从入门到实战
  • 布丁扫描高级会员版 v3.5.2.2| 安卓智能扫描 APP OCR文字识别小助手
  • 可视化大屏全屏后重载echarts图表
  • 20200201工作笔记常用命令要整理
  • Java对象内存模型、如何判定对象已死亡?
  • spark任务的提交流程
  • ELK简介和docker版安装
  • 利用条件编译实现RTT可控的调试输出
  • 【软件设计师】计算机网络考点整理
  • 智慧化工园区安全风险管控平台建设方案(Word)
  • 【uniapp】 iosApp开发xcode原生配置项(iOS平台Capabilities配置)
  • MYSQL优化(1)
  • C++可变参数宏定义语法笔记
  • 基于BERT预训练模型(bert_base_chinese)训练中文文本分类任务(AI老师协助编程)
  • Windows逆向工程提升之IMAGE_EXPORT_DIRECTORY
  • python与flask框架
  • 【普及+/提高】洛谷P2613 【模板】有理数取余——快读+快速幂
  • 从数据到智能:openGauss+openEuler Intelligence的RAG架构实战
  • 【Linux】初见,基础指令
  • 什么是实时流数据?核心概念与应用场景解析
  • 工业RTOS生态重构:从PLC到“端 - 边 - 云”协同调度
  • 数据结构与算法学习笔记(Acwing 提高课)----动态规划·状态机模型
  • 基于开源链动2+1模式AI智能名片S2B2C商城小程序的社群构建与新型消费迎合策略研究
  • 高性能RPC框架--Dubbo(五)
  • 计算机视觉与深度学习 | PSO-MVMD粒子群算法优化多元变分模态分解(Matlab完整代码和数据)
  • 搭建自己的语音对话系统:开源 S2S 流水线深度解析与实战
  • feign调用指定服务ip端口
  • 【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】
  • vue2 中的过滤器以及vue3中的替换方案