【创造型模式】工厂方法模式
文章目录
- 工厂方法模式
- 工厂方法模式当中的角色和职责
- 工厂方法模式的实现
- 工厂方法模式的优缺点
工厂方法模式
今天我们继续学习一例创造型设计模式——工厂方法模式。参考的主要资料是刘丹冰老师的《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()
}
可以看到,新增的基本类“山东苹果”和“山东苹果工厂”没有改动之前的任何代码,完全符合开闭原则思想。新增的功能不会影响到之前已有系统的稳定性。与之相比,如果采用简单工厂模式,那么针对新增的“山东苹果”产品,必须修改工厂,添加与“山东苹果”相关的生产逻辑,这样就会改动已有的业务逻辑,不够好。
工厂方法模式的优缺点
优点
- 不需要记住具体类名,甚至连具体参数都不需要记忆;
- 实现了对象创建和使用的分离;
- 系统的可拓展性非常好,无需改动接口和原类;
- 新产品的创建符合开闭原则。
缺点
- 会增加系统中类的个数,复杂度增加,需要更长的时间理解;
- 增加了系统的抽象性和理解难度。
适用场景
- 客户端不知道它需要的对象的类。
- 抽象工厂类通过其子类来指定创建哪个对象。
相关文章:

【创造型模式】工厂方法模式
文章目录 工厂方法模式工厂方法模式当中的角色和职责工厂方法模式的实现工厂方法模式的优缺点 工厂方法模式 今天我们继续学习一例创造型设计模式——工厂方法模式。参考的主要资料是刘丹冰老师的《Easy 搞定 Golang 设计模式》。 工厂方法模式当中的角色和职责 简单来说&…...

【MySQL】使用文件进行交互
目录 准备工作 1.从文本文件中读取数据(导入) 1.1.CSV 文件 1.2.设置导入导出的路径 1.3.导入文件 1.4.将数据写入文本文件(导出) 2.从文件中读取并执行SQL命令 2.1.通过mysql监视器执行编写在文件里面的SQL语句 2.2.通过…...

# 大模型的本地部署与应用:从入门到实战
大模型的本地部署与应用:从入门到实战 在当今人工智能飞速发展的时代,大模型(尤其是大型语言模型,LLMs)已经成为自然语言处理(NLP)领域的核心力量。从文本生成、机器翻译到问答系统,…...
布丁扫描高级会员版 v3.5.2.2| 安卓智能扫描 APP OCR文字识别小助手
布丁扫描高级会员版 v3.5.2.2| 安卓智能扫描 APP OCR文字识别小助手 布丁扫描APP是一款集成了先进图像处理与OCR文字识别技术的智能扫描软件。它旨在将纸质文档、照片、名片、书籍等各类实体资料快速…...
可视化大屏全屏后重载echarts图表
问题:可视化大屏点击全屏之后,但echarts图表还是之前的大小,并没有撑满该容器,所以这时候我们需要全屏之后重新加载echarts图表内容 代码如下: // 全屏或非全屏状态下重新加载图表window.onresize () > {//lineCh…...
20200201工作笔记常用命令要整理
工作笔记常用命令: 1.repo常用命令: repo sync -c -j10 2. 常用adb命令 错误: error: device unauthorized. This adbds $ADB_VENDOR_KEYS is not set; try adb kill-server if that seems wrong. Otherwise check for a confirmation dialog on your d…...

Java对象内存模型、如何判定对象已死亡?
一、Java对象内存模型 Java对象在内存中由三部分组成: 含类元数据指针(指向方法区的Class对象)和Mark Word(存储对象哈希码、锁状态、GC分代年龄等信息)。 若为数组对象,还包含数组长度数据。 1,…...
spark任务的提交流程
目录 spark任务的提交流程1. 资源申请与初始化2. 任务划分与调度3. 任务执行4. 资源释放与结果处理附:关键组件协作示意图扩展说明SparkContext介绍 spark任务的提交流程 用户创建一个 Spark Context;Spark Context 去找 Cluster Manager 申请资源同时说明需要多少 CPU 和内…...
ELK简介和docker版安装
使用场景 主要还是给开发人员“打捞日志”用的。 ELK 是由三个开源工具组成的套件(Elasticsearch、Logstash 和 Kibana),主要用于日志的收集、分析和可视化。以下是 ELK 常见的使用场景: 日志集中化管理 收集来自多个服务器或服…...
利用条件编译实现RTT可控的调试输出
在嵌入式开发中,调试信息的输出通常对定位问题至关重要。然而,为了保证代码在正式发布时的性能和体积,调试信息往往需要在不修改主逻辑代码的前提下禁用。 代码一览 // debug.h #pragma once// #define DEBUG#ifdef DEBUG#include "SEG…...
【软件设计师】计算机网络考点整理
以下是软件设计师考试中 计算机网络 的核心考点总结,帮助您高效备考: 一、网络体系结构与协议 OSI七层模型 & TCP/IP四层模型 各层功能(物理层-数据链路层-网络层-传输层-会话层-表示层-应用层)对应协…...

智慧化工园区安全风险管控平台建设方案(Word)
1 项目概况 1.1 园区概况 1.1.1 XX化工园区简况 1.1.2 企业现状 1.1.3 园区发展方向 1.1.4 园区信息化现状 1.2 项目建设背景 1.2.1 政策背景 1.3 项目建设需求分析 1.3.1 政策需求分析 1.3.2 安全生产监管需求分析 1.3.3 应急协同管理需求分析 1.3.4 工业互联网安…...

【uniapp】 iosApp开发xcode原生配置项(iOS平台Capabilities配置)
如果你需要配置诸如:Access Wi-Fi Information 简单地说就是这个地址 ios平台capabilities配置 本来这种配置就是在Xcode的平台中选中即可,他们的信息会存储在XCode工程的.entitlements和Info.plist文件。 按照uniapp文档说的, HBuilderX4.…...

MYSQL优化(1)
MYSQL调优强调的是如何提高MYSQL的整体性能,是一套整体方案。根据木桶原理,MYSQL的最终性能取决于系统中性能表现最差的组件。可以这样理解,即使MYSL拥有充足的内存资源,CPU资源,如果外存IO性能低下,那么系…...
C++可变参数宏定义语法笔记
1. 基础语法 定义格式: #define MACRO_NAME(fixed_args, ...) macro_body#define LOG(fmt, ...) printf(fmt, __VA_ARGS__) LOG("Value: %d, Name: %s", 42, "Alice"); // 展开为 printf("Value: %d, Name: %s", 42, "Alice&q…...

基于BERT预训练模型(bert_base_chinese)训练中文文本分类任务(AI老师协助编程)
新建项目 创建一个新的虚拟环境 创建新的虚拟环境(大多数时候都需要指定python的版本号才能顺利创建): conda create -n bert_classification python3.9激活虚拟环境: conda activate myenvPS:虚拟环境可以避免权限问题,并隔离…...
Windows逆向工程提升之IMAGE_EXPORT_DIRECTORY
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 什么是 IMAGE_EXPORT_DIRECTORY? PE 文件与 Export Table 的关系 PE 文件的整体视角 Export Table 在 PE 中的定位 IMAGE_EXPORT_DIRECTORY 结构 数据结构定义 字段详解…...
python与flask框架
一、理论 Flask是一个轻量级的web框架,灵活易用。提供构建web应用所需的核心工具。 Flask依赖python的两个库 Werkzeug:flask的底层库,提供了WSGI接口、HTTP请求和响应处理、路由等核心功能。 Jinja2:模板引擎࿰…...
【普及+/提高】洛谷P2613 【模板】有理数取余——快读+快速幂
题目来源 P2613 【模板】有理数取余 - 洛谷 题目描述 给出一个有理数 cba,求 cmod19260817 的值。 这个值被定义为 bx≡a(mod19260817) 的解。 输入格式 一共两行。 第一行,一个整数 a。 第二行,一个整数 b。 输出格式 一个整数&a…...

从数据到智能:openGauss+openEuler Intelligence的RAG架构实战
随着人工智能和大规模语言模型技术的崛起,传统的搜索引擎由于其只能提供简单的关键字匹配结果,已经越来越无法满足用户对于复杂、多样化和上下文相关的知识检索需求。与此相对,RAG(Retrieval-Augmented Generation)技术…...

【Linux】初见,基础指令
前言 本文将讲解Linux中最基础的东西-----指令,带大家了解一下Linux中有哪些基础指令,分别有什么作用。 本文中的指令和选项并不全,只介绍较为常用的 pwd指令 语法:pwd 功能:显示当前所在位置(路径…...

什么是实时流数据?核心概念与应用场景解析
在当今数字经济时代,实时流数据正成为企业核心竞争力。金融机构需要实时风控系统在欺诈交易发生的瞬间进行拦截;电商平台需要根据用户实时行为提供个性化推荐;工业物联网需要监控设备状态预防故障。这些场景都要求系统能够“即时感知、即时分…...

工业RTOS生态重构:从PLC到“端 - 边 - 云”协同调度
一、引言 在当今数字化浪潮席卷全球的背景下,工业领域正经历着深刻变革。工业自动化作为制造业发展的基石,其技术架构的演进直接关系到生产效率、产品质量以及企业的市场竞争力。传统的PLC(可编程逻辑控制器)架构虽然在工业控制领…...
数据结构与算法学习笔记(Acwing 提高课)----动态规划·状态机模型
数据结构与算法学习笔记----动态规划状态机模型 author: 明月清了个风 first publish time: 2025.5.20 ps⭐️背包终于结束了,状态机模型题目不多。状态机其实是一种另类的状态表示方法,将某一个点扩展为一个状态进行保存并在多个状态之间转移…...

基于开源链动2+1模式AI智能名片S2B2C商城小程序的社群构建与新型消费迎合策略研究
摘要:随着个性化与小众化消费的崛起,消费者消费心理和模式发生巨大变化,社群构建对商家迎合新型消费特点、融入市场经济发展至关重要。开源链动21模式AI智能名片S2B2C商城小程序的出现,为社群构建提供了创新工具。本文探讨该小程序…...

高性能RPC框架--Dubbo(五)
Filter: filter过滤器动态拦截请求(request)或响应(response)以转换或使用请求或响应中包含的信息。同时对于filter过滤器不仅适合消费端而且还适合服务提供端。我们可以自定义在什么情况下去使用filter过滤器 Activa…...
计算机视觉与深度学习 | PSO-MVMD粒子群算法优化多元变分模态分解(Matlab完整代码和数据)
以下是一个基于PSO优化多元变分模态分解(MVMD)的Matlab示例代码框架,包含模拟数据生成和分解结果可视化。用户可根据实际需求调整参数。 %% 主程序:PSO优化MVMD参数 clc; clear; close all;% 生成模拟多变量信号 fs = 1000; % 采样频率 t = 0:1/fs:...

搭建自己的语音对话系统:开源 S2S 流水线深度解析与实战
网罗开发 (小红书、快手、视频号同名) 大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等…...

feign调用指定服务ip端口
1 背景 在springcloud开发时候,同时修改了feign接口和调用方的代码,希望直接在某个环境调用修改的代码,而线上的服务又不希望被下线因为需要继续为其他访问页面的用户提供功能后端服务,有时候甚者包含你正在修改的功能。 2 修改…...

【深尚想!爱普特APT32F1023H8S6单片机重构智能电机控制新标杆】
在智能家电与健康器械市场爆发的今天,核心驱动技术正成为产品突围的关键。传统电机控制方案面临集成度低、开发周期长、性能瓶颈三大痛点,而爱普特电子带来的APT32F1023H8S6单片机无感三合一方案,正在掀起一场智能电机控制的技术革命。 爆款基…...