比简单工厂更好的 - 工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern)
- 工厂方法模式(Factory Method Pattern)
- 工厂方法模式(Factory Method Pattern)概述
- 工厂方法模式(Factory Method Pattern)结构图
- 工厂方法模式(Factory Method Pattern)涉及的角色
- talk is cheap, show you my code
- 总结
工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它提供了一种创建对象的接口,但由子类决定要实例化的类是哪一个。这种模式让类的实例化推迟到子类,从而实现了创建逻辑与具体实现的分离。通过这种方式,工厂方法模式使得一个框架可以不依赖于具体的类,而只依赖于抽象类或接口,提高了代码的灵活性和可扩展性。
太抽象了
我们先说一下简单工厂,简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。
相当于我们有一个工厂类,有一个工厂方法,我们给这个工厂方法传入不同的参数,这个工厂就给我生成不同的对象。但是简单工厂有一个问题就是,如果我们要新增产品,我们就需要修改工厂方法。这样就违反了开闭原则。
工厂方法模式(Factory Method Pattern)概述
工厂方法模式(Factory Method Pattern)结构图

工厂方法模式(Factory Method Pattern)涉及的角色
- 产品接口(Product):声明了所有具体产品必须实现的操作。所有的具体产品类都实现了这个接口或继承自这个抽象类。
public interface Product {void operation();
}
- 具体产品(ConcreteProduct):实现了Product接口,提供了具体产品的实现。
public class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}public class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}
- 创建者/工厂接口(Creator):接口或抽象类,声明了工厂方法,该方法返回Product类型的对象。创建者还可以包含其他业务逻辑,这些逻辑可以调用工厂方法来创建产品对象。
public abstract class Creator {// 工厂方法public abstract Product factoryMethod();// 其他业务逻辑public void someOperation() {Product product = this.factoryMethod();product.operation(); // 使用创建的产品}
}
- 具体创建者(ConcreteCreator):实现了Creator中的工厂方法,每个具体创建者都会返回不同类型的Product对象。
public class ConcreteCreatorA extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductA();}
}public class ConcreteCreatorB extends Creator {@Overridepublic Product factoryMethod() {return new ConcreteProductB();}
}
talk is cheap, show you my code
// 定义产品接口
public interface Shape {void draw();
}// 实现具体产品
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a circle.");}
}public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a rectangle.");}
}// 定义创建者接口
public abstract class ShapeFactory {public abstract Shape createShape();public void drawShape() {Shape shape = createShape();shape.draw();}
}// 实现具体创建者
public class CircleFactory extends ShapeFactory {@Overridepublic Shape createShape() {return new Circle();}
}public class RectangleFactory extends ShapeFactory {@Overridepublic Shape createShape() {return new Rectangle();}
}// 客户端代码
public class Client {public static void main(String[] args) {ShapeFactory circleFactory = new CircleFactory();circleFactory.drawShape(); // Drawing a circle.ShapeFactory rectangleFactory = new RectangleFactory();rectangleFactory.drawShape(); // Drawing a rectangle.}
}
工作流程
- 客户端创建具体的工厂对象(如 CircleFactory 或 RectangleFactory)。
- 调用工厂对象的 drawShape() 方法。
- drawShape() 方法内部调用 createShape() 方法,由具体的工厂子类决定创建哪种类型的 Shape 实例。
- 创建的 Shape 实例的 draw() 方法被执行,输出相应的绘制信息。
总结
工厂方法模式的优点
- 遵循开闭原则:新增加产品时,只需要添加新的具体产品类和对应的创建者类,无需修改现有代码,这符合面向对象设计中的开闭原则(Open/Closed Principle)。
- 支持多态行为:客户端代码可以通过基类或接口来操作对象,而不需要关心具体的产品类型。
- 解耦合:工厂方法模式将创建对象的责任推给了子类,减少了客户端代码与具体产品之间的耦合度。
- 易于扩展:当需要引入新产品时,只需创建相应的产品类和创建者类即可,而不必修改现有代码。
工厂方法模式的具体应用场景
- 创建复杂对象:当对象的创建过程较为复杂时,可以使用工厂方法模式将创建逻辑封装起来。
- 不确定具体类型:当你事先不知道需要创建哪种类型的对象时,可以使用工厂方法模式,在运行时根据条件动态选择。
- 代码重构:如果你发现代码中有大量的条件判断用来创建不同类型的对象,那么可以考虑使用工厂方法模式来重构代码,使其更加简洁和易于维护。
- 框架开发:在开发框架时,工厂方法模式可以让框架用户通过继承来定制化对象的创建过程,而不需要修改框架本身的代码。
什么时候考虑使用工厂方法模式
- 当一个类不知道它所必须创建的对象的类时。
- 当一个类希望由它的子类来指定它所创建的对象时。
- 当类将创建对象的职责委托给多个帮助子类中的某一个,并且你希望将哪一个帮助子类是代理者这一信息局部化时。
工厂方法模式提供了一种有效的方式来解耦对象的创建与使用,使得系统更加灵活和易于扩展。对于那些需要根据条件动态创建不同类型对象的情况,工厂方法模式是一个非常有用的工具。理解如何正确使用工厂方法模式可以帮助开发者构建更加模块化和易于维护的软件系统。
相关文章:
比简单工厂更好的 - 工厂方法模式(Factory Method Pattern)
工厂方法模式(Factory Method Pattern) 工厂方法模式(Factory Method Pattern)工厂方法模式(Factory Method Pattern)概述工厂方法模式(Factory Method Pattern)结构图工厂方法模式&…...
分布式搜索引擎02
1. DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1. DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据,…...
阿里云安装mikrotik7配置内网互通
阿里云近期推出了200M不限量机器,对于没有公网接入的中小企业可以借助这个机器对多地分支机构进行内网互通。目前已经有很多机构用这个搞跨云k8s,跨云集群了。 mikrotik作为一个商用的软件,操作性比一些开源的软件好用不少。 本文使用的网段为172.16.1…...
Docker网段和服务器ip冲突导致无法访问网络的解决方法
若宿主机所在网络的网段为172.[17-31].xx.xx,则会与Docker本身内部网络间出现冲突,此时需要重新配置Docker默认地址池 一:查看docker的默认网段 route 二:修改docker的默认网段 etc/docker/daemon.json文件增加修改网段信息 {…...
Kubernetes 集群中安装和配置 Kubernetes Dashboard
前言 上篇成功部署Kubernetes集群后,为了方便管理和监控集群资源,安装Kubernetes Dashboard显得尤为重要。Kubernetes Dashboard 是一个通用的、基于 Web 的 UI,旨在让用户轻松地部署容器化应用到 Kubernetes 集群,并对这些应用进…...
Android开发之Spinner
Android开发之Spinner 1. 概述2. Spinner3. 适配器3.1 ArrayAdapter3.2 SimpleAdapter 1. 概述 Android开发学习笔记。学习下拉框控件Spinner和适配器(数组适配器ArrayAdapter、简单适配器SimpleAdapter)的使用。 2. Spinner 下拉框控件,用…...
【c++继承篇】--继承之道:在C++的世界中编织血脉与传承
目录 引言 一、定义二、继承定义格式2.1定义格式2.2继承关系和访问限定符2.3继承后子类访问权限 三、基类和派生类赋值转换四、继承的作用域4.1同名变量4.2同名函数 五、派生类的默认成员构造函数5.1**构造函数调用顺序:**5.2**析构函数调用顺序:**5.3调…...
分布式系统通信解决方案:Netty 与 Protobuf 高效应用
分布式系统通信解决方案:Netty 与 Protobuf 高效应用 一、引言 在现代网络编程中,数据的编解码是系统设计的一个核心问题,特别是在高并发和低延迟的应用场景中,如何高效地序列化和传输数据对于系统的性能至关重要。随着分布式系…...
计算机网络 (54)系统安全:防火墙与入侵检测
前言 计算机网络系统安全是确保网络通信和数据不受未经授权访问、泄露、破坏或篡改的关键。防火墙和入侵检测系统(IDS)是维护网络系统安全的两大核心组件。 一、防火墙 定义与功能 防火墙是一种用来加强网络之间访问控制的特殊网络互联设备,它…...
stack底层实现细节
一、stack 和 queue 在 STL 中 stack 和 queue 已经不算是容器了,而是容器适配器,适配器模式也是常用的模式之一,体现在 stack 和 queue 中就是他们两个的实现不是单独写的,而是复用了前面合适的优秀的STL 容器的代码而实现的具有…...
工业相机 SDK 二次开发-Halcon 插件
本文介绍了 Halcon 连接相机时插件的使用。通过本套插件可连接海康 的工业相机。 一. 环境配置 1. 拷贝动态库 在 用 户 安 装 MVS 目 录 下 按 照 如 下 路 径 Development\ThirdPartyPlatformAdapter 找到目录为 HalconHDevelop 的文 件夹,根据 Halcon 版本找到对…...
map和set的使用(一)详解
文章目录 序列式容器和关联式容器map和set的介绍set构造和迭代器遍历和insertfinderaseswapclearcountlower_bound和upper_boundmultiset和set的对比 set的二个题目题目解析算法原理代码介绍一个找差集的算法同步算法题目解析算法原理代码 map构造遍历initiaizer_list 序列式容…...
ARP 表、MAC 表、路由表、跨网段 ARP
文章目录 一、ARP 表1、PC2、路由器 - AR22203、交换机 - S57004、什么样的设备会有 ARP 表? 二、MAC 表什么样的设备会有 MAC 表? 三、路由表什么样的设备会有路由表? 四、抓取跨网段 ARP 包 所谓 “透明” 就是指不用做任何配置 一、ARP 表…...
37.构造回文字符串问题|Marscode AI刷题
1.题目 问题描述 小C手中有一个由小写字母组成的字符串 s。她希望构造另一个字符串 t,并且这个字符串需要满足以下几个条件: t 由小写字母组成,且长度与 s 相同。t 是回文字符串,即从左到右与从右到左读取相同。t 的字典序要小…...
ssm-mybatisPlus学习笔记
注意!mybatisPlus只能够进行单表操作,其他的仍需要mybatis 1.快速入门 编写启动类 MapperScan("com.atguigu.mapper") SpringBootApplication public class MainApplication {public static void main(String[] args) {SpringApplication.r…...
【算法学习笔记】35:扩展欧几里得算法求解线性同余方程
线性同余方程问题 线程同余方程问题是指 a x ≡ b ( m o d m ) ax \equiv b~(mod~m) ax≡b (mod m),给定 a a a、 b b b和 m m m,找到一个整数 x x x使得该方程成立,即使得 a x m o d m b ax~mod~mb ax mod mb,随便返回任何一个…...
线性规划:机器学习中的优化利器
一、线性规划的基本概念 线性规划(Linear Programming, LP)是运筹学中数学规划的一个重要分支,用于在一组线性不等式的约束条件下,找到线性目标函数的最大值或最小值。其问题可以表述为: 在一组线性约束条件 s.t.&am…...
Ubuntu开发中的问题
1.退出anaconda指令:conda deactivate 2.Linux系列:一打开终端就默认进入conda的base环境,取消方法 在终端输入conda config --show,会显示所有的配置信息,然后利用conda config --set来修改此配置: conda config --se…...
MAC 地址转换为标准大写格式
// ConvertToStandardMac 将 MAC 地址转换为标准格式,确保每个字节都是两位,并且字母是大写的 func ConvertToStandardMac(mac string) (string, error) { // 分割 MAC 地址的每一部分 parts : strings.Split(mac, ":") // 确保每部分是两…...
使用插件SlideVerify实现滑块验证
作者gitee地址:https://gitee.com/monoplasty/vue-monoplasty-slide-verify 使用步骤: 1、安装插件 npm install --save vue-monoplasty-slide-verify 2、在main.js中进行配置 import SlideVerify from vue-monoplasty-slide-verify; Vue.use(SlideV…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
作为测试我们应该关注redis哪些方面
1、功能测试 数据结构操作:验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化:测试aof和aof持久化机制,确保数据在开启后正确恢复。 事务:检查事务的原子性和回滚机制。 发布订阅:确保消息正确传递。 2、性…...
STM32---外部32.768K晶振(LSE)无法起振问题
晶振是否起振主要就检查两个1、晶振与MCU是否兼容;2、晶振的负载电容是否匹配 目录 一、判断晶振与MCU是否兼容 二、判断负载电容是否匹配 1. 晶振负载电容(CL)与匹配电容(CL1、CL2)的关系 2. 如何选择 CL1 和 CL…...
C# winform教程(二)----checkbox
一、作用 提供一个用户选择或者不选的状态,这是一个可以多选的控件。 二、属性 其实功能大差不差,除了特殊的几个外,与button基本相同,所有说几个独有的 checkbox属性 名称内容含义appearance控件外观可以变成按钮形状checkali…...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
C++ 类基础:封装、继承、多态与多线程模板实现
前言 C 是一门强大的面向对象编程语言,而类(Class)作为其核心特性之一,是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性,包括封装、继承和多态,同时讨论类中的权限控制,并展示如何使用类…...
Springboot 高校报修与互助平台小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,高校报修与互助平台小程序被用户普遍使用,为…...
