【创建型设计模式】工厂模式

【创建型设计模式】工厂模式

创建型设计模式第二期!本期介绍简单工厂模式和工厂方法模式。

简单工厂模式

简单工厂模式(又叫作静态工厂方法模式),其属于创建型设计模式,简单工厂模式不属于设计模式中的 23 种经典模式。提到它是为了让大家能够更好地理解后面讲到的工厂方法模式。

定义:简单工厂模式属于创建型设计模式,其又被称为静态工厂方法模式,这是由一个工厂对象决定创建出哪一种产品类的实例。

简单工厂模式通过工厂类的静态方法,根据传入的参数创建并返回不同的产品对象。

在简单工厂模式中有如下角色:

  • Factory: 工厂类,这是简单工厂模式的核心,它负责实现创建所有实例的内部逻辑。工厂类的创建产品类的方法可以被外界直接调用,创建所需的产品对象。
  • Product: 抽象产品类,这是简单工厂模式所创建的所有对象的父类,它负责描述所有实例所共有的公共接口。
  • Product: 具体产品类,这是简单工厂模式的创建目标。

省流:

工厂类(Factory):负责创建具体产品实例的类。

抽象产品(Product):所有具体产品的父类或接口。

具体产品(Concrete Product):工厂类所创建的具体对象。

1. 简单工厂模式的简单实现

这里我们用生产计算机来举例,假设有一个计算机的代工生产商,它目前已经可以代工生产联想计算机了。随着业务的拓展,这个代工生产商还要生产惠普和华硕的计算机。这样我们就需用一个单独的类来专门生产计算机,这就用到了简单工厂模式,下面我们来实现简单工厂模式。

(1)抽象产品类 (Shape 接口)
// 抽象产品
public interface Shape {void draw();
}

目的

定义统一的产品接口,所有具体产品都必须实现该接口。

面向接口编程:客户端只需要知道 Shape 的接口,而不需要关心具体实现。

优点

增强了代码的灵活性,客户端可以通过 Shape 类型调用 draw 方法,减少对具体类的依赖。

(2)具体产品类(Circle, Rectangle, Triangle 类)
// 圆形
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 class Triangle implements Shape {@Overridepublic void draw() {System.out.println("Drawing a Triangle");}
}
目的

这些类是具体实现,负责实现抽象产品 (Shape) 中的接口方法。

每个具体产品有其独特的行为逻辑。例如,Circle.draw 可能涉及圆的特定绘制逻辑。

优点

将每个形状的行为封装在独立的类中,满足单一职责原则。

(3)工厂类(ShapeFactory)
// 工厂类
public class ShapeFactory {public static Shape createShape(String shapeType) {if ("circle".equalsIgnoreCase(shapeType)) {return new Circle();} else if ("rectangle".equalsIgnoreCase(shapeType)) {return new Rectangle();} else if ("triangle".equalsIgnoreCase(shapeType)) {return new Triangle();} else {throw new IllegalArgumentException("Unknown shape type: " + shapeType);}}
}

目的

封装对象创建逻辑:工厂类中定义了如何根据传入参数决定返回哪种 Shape 对象。

隐藏具体实现:客户端无需知道具体类名,只需通过简单的字符串参数即可获得对象实例。

实现细节

静态方法 createShape:接收一个字符串 shapeType,通过条件判断实例化对应的 Shape 对象。

错误处理:如果传入的 shapeType 无法匹配现有的类型,则抛出 IllegalArgumentException,确保程序不会意外运行。

优点

客户端与具体实现解耦,符合 依赖倒置原则

通过集中管理对象创建逻辑,可以减少冗余代码。

缺点

每增加一种产品,都需要修改 ShapeFactory 的代码,违反了 开闭原则

(4)客户端调用工厂类
public class Main {public static void main(String[] args) {// 使用工厂创建对象Shape circle = ShapeFactory.createShape("circle");circle.draw();Shape rectangle = ShapeFactory.createShape("rectangle");rectangle.draw();Shape triangle = ShapeFactory.createShape("triangle");triangle.draw();}
}
功能

客户端通过 ShapeFactory 的静态方法获取具体的 Shape 对象。

无需直接调用 new Circle()new Rectangle(),只需提供字符串参数即可完成对象的创建。

优点

客户端的代码更简洁,只需与 ShapeFactoryShape 接口交互。

隐藏了对象的具体实现,降低了耦合性。

2. 使用简单工厂模式的场景和优缺点

1. 客户端不需要关心对象创建的复杂过程

如果对象的创建涉及复杂的逻辑或依赖大量配置参数,而客户端只关心最终的产品实例,则可以使用简单工厂模式。

示例:日志记录系统根据参数返回文件日志、数据库日志、或控制台日志实例。

2. 产品种类有限且变化不频繁

当需要创建的产品种类数量较少,且不需要频繁扩展或修改时,简单工厂是一个快速实现的选择。

示例:为小型电商系统创建不同类型的支付方式(如支付宝、微信支付、信用卡支付)。

3. 需要在运行时动态决定使用哪个产品

当具体产品的选择需要根据运行时的条件决定,而这些条件可以通过参数来表示时,简单工厂模式非常适用。

示例:根据文件类型(如 .txt, .pdf)返回相应的文件解析器对象。

工厂方法模式

工厂方法模式(Factory Method Pattern)是一种 创建型设计模式,它通过定义一个抽象的工厂接口,由子类决定具体实例化的产品对象,从而让对象的创建延迟到子类中进行。

在工厂方法模式中有如下角色:

抽象工厂(Factory Interface/Abstract Factory)

  • 定义工厂的通用接口,提供一个用于创建产品的方法。

具体工厂(Concrete Factory)

  • 实现抽象工厂接口,负责具体产品的实例化。

抽象产品(Product Interface/Abstract Product)

  • 定义产品的公共接口,确保不同的产品有相同的行为。

具体产品(Concrete Product)

  • 实现抽象产品接口,提供具体的产品功能。
image-20241124003745585

工厂方法模式的优缺点

优点

符合开闭原则

  • 增加新产品时,只需添加对应的具体工厂类,而无需修改已有代码。

高内聚低耦合

  • 客户端依赖于抽象工厂和抽象产品,减少了对具体实现的耦合。

代码更灵活

  • 客户端可以通过切换具体工厂来获得不同的产品实例,而无需更改业务代码。
缺点

增加了系统复杂度

  • 每增加一种产品,就需要增加一个具体工厂类,类的数量会随着产品类型的增加而增加。

不适合产品种类较少的场景

  • 如果产品种类较少,使用工厂方法模式可能会导致代码结构过于冗长。

工厂方法模式的简单实现

工厂方法模式的抽象产品类与具体产品类的创建和简单工厂模式是一样的。

(1)创建抽象工厂
// 抽象工厂接口
public interface ParserFactory {DocumentParser createParser();
}
(2)创建具体工厂
// Word 文档解析器工厂
public class WordParserFactory implements ParserFactory {@Overridepublic DocumentParser createParser() {return new WordParser();}
}// PDF 文档解析器工厂
public class PdfParserFactory implements ParserFactory {@Overridepublic DocumentParser createParser() {return new PdfParser();}
}
(3)抽象产品
// 抽象产品接口
public interface DocumentParser {void parse(String content);
}
(4)具体产品
// Word 文档解析器
public class WordParser implements DocumentParser {@Overridepublic void parse(String content) {System.out.println("Parsing Word document: " + content);}
}// PDF 文档解析器
public class PdfParser implements DocumentParser {@Overridepublic void parse(String content) {System.out.println("Parsing PDF document: " + content);}
}
(5)客户端代码
public class Main {public static void main(String[] args) {// 使用工厂方法创建解析器ParserFactory wordFactory = new WordParserFactory();DocumentParser wordParser = wordFactory.createParser();wordParser.parse("This is a Word document");ParserFactory pdfFactory = new PdfParserFactory();DocumentParser pdfParser = pdfFactory.createParser();pdfParser.parse("This is a PDF document");}
}

工厂方法模式与简单工厂模式

特性简单工厂模式工厂方法模式
创建逻辑由单一工厂类负责,集中管理创建逻辑每个具体工厂负责创建特定类型的产品
扩展性修改工厂类即可扩展产品,但违反开闭原则添加新产品时只需添加新的工厂类,符合开闭原则
适用场景产品种类较少,变化不频繁产品种类较多,变化频繁,需要满足扩展性要求
类的复杂度工厂类单一,代码量少增加每种产品时需要增加对应的工厂类,类的数量较多
客户端与工厂的关系客户端依赖于具体的工厂类客户端依赖于抽象工厂,屏蔽具体实现细节

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/61773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ和RocketMQ相关面试题

RabbitMQ和RocketMQ面试题 RabbitMQ1.RabbitMQ各部分角色2.如何确保RabbitMQ消息的可靠性?3.什么样的消息会成为死信?4.死信交换机的使用场景是什么?5.TTL6.延迟队列7.消息堆积问题8.MQ集群 RocketMQ1.RocketMQ各部分角色2.RocketMQ如何保证高…

基于LLama_factory的Qwen2.5大模型的微调笔记

Qwen2.5大模型微调记录 LLama-facrotyQwen2.5 模型下载。huggingface 下载方式Modelscope 下载方式 数据集准备模型微调模型训练模型验证及推理模型导出 部署推理vllm 推理Sglang 推理 LLama-facroty 根据git上步骤安装即可,要求的软硬件都装上。 llama-factory运行…

Linux系统Docker部署开源在线协作笔记Trilium Notes与远程访问详细教程

目录 ⛳️推荐 前言 1. 安装docker与docker-compose 2. 启动容器运行镜像 3. 本地访问测试 4.安装内网穿透 5. 创建公网地址 6. 创建固定公网地址 ⛳️推荐 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下…

Spark——安装步骤详细教程

1、安装步骤 1、上传 cd /opt/modules 2、解压 tar -zxf spark-3.1.2-bin-hadoop3.2.tgz -C /opt/installs 3、重命名 cd /opt/installs mv spark-3.1.2-bin-hadoop3.2 spark-local 4、创建软链接 ln -s spark-local spark 5、配置环境变量: vi /etc/prof…

Vue第一篇:组件模板总结

前言 本文希望读者有一定的Vue开发经验&#xff0c;样例采用vue中的单文件组件&#xff0c;也是我的个人笔记&#xff0c;欢迎一起进步 必须有根元素 这是一个最简单的vue单文件组件&#xff0c;<template></template>被称为模板&#xff0c;模板中必须有一个根元素…

MacOS通过X11转发远程运行virt-manager进行虚机分配

今天需要通过本地macbook机器连接远程物理机&#xff0c;执行虚机分配&#xff0c;现有文档仅提供window环境安装&#xff0c;如下整理Mac环境下的安装步骤 操作篇 前提条件 支持x11转发的terminal&#xff0c;我本地使用iTerm2&#xff1b;本地安装XQuartz&#xff0c;作为…

flowable流程图详细绘制教程

文章目录 前言一、flowable是什么&#xff1f;回答下之前的问题 二、flowable-modeler使用1. 使用步骤2.开始绘制弄一个请假的流程 三 加载该流程总结 前言 flowable有些晦涩难懂的东西&#xff1a; 我最开始接触的时候,还是用的activity,当时觉得好复杂,那么这次经过我自己在…

C/C++链接数据库(MySQL)(超级详细)

目录 1.进入MySQL后&#xff0c;用mysql数据库 1.1查看一看user表 ​编辑1.2从user拿出来User和Host 1.3创建一个用户表&#xff0c;只允许本地&#xff08;想要远端链接就把localhost改成%&#xff09; 1.4再查一下用户就有了&#xff08;connector&#xff09; 1.5测试…

Jmeter中的定时器

4&#xff09;定时器 1--固定定时器 功能特点 固定延迟&#xff1a;在每个请求之间添加固定的延迟时间。精确控制&#xff1a;可以精确控制请求的发送频率。简单易用&#xff1a;配置简单&#xff0c;易于理解和使用。 配置步骤 添加固定定时器 右键点击需要添加定时器的请求…

msvcr100.dll丢失的解决方法,六种解决msvcr100.dll丢失的方法

在使用Windows操作系统的过程中&#xff0c;用户可能会遇到各种各样的问题&#xff0c;其中之一就是“msvcr100.dll丢失”的错误提示。这个问题通常出现在尝试运行某些软件或游戏时&#xff0c;由于缺少这个重要的动态链接库文件&#xff0c;导致程序无法正常启动。本文将详细介…

排序(Java数据结构)

1. 排序的概念及引用 1.1 排序的概念 排序&#xff1a;所谓排序&#xff0c;就是使一串记录&#xff0c;按照其中的某个或某些关键字的大小&#xff0c;递增或递减的排列起来的操作。(所有的排序都是默认从小到大排序) 稳定性&#xff1a;假定在待排序的记录序列中&#xff…

VH6501国产替代同星TH7011干扰仪?

文章目录 同星TH7011干扰仪VH6501有使用过TH7011的么,可以在评论区讨论一下~ 同星TH7011干扰仪 干货分享 | 一文详解同星CAN总线干扰仪的使用方法 VH6501

蓝桥杯每日真题 - 第23天

题目&#xff1a;&#xff08;直线&#xff09; 题目描述&#xff08;12届 C&C B组C题&#xff09; 解题思路&#xff1a; 题目理解: 在平面直角坐标系中&#xff0c;从给定的点集中确定唯一的直线。 两点确定一条直线&#xff0c;判断两条直线是否相同&#xff0c;可通过…

目录遍历漏洞-CVE-2021-41773

目录 简介 原理 例子 Apache路径穿越漏洞 环境搭建 漏洞原理 漏洞利用 简介 目录遍历漏洞&#xff08;也称为路径遍历漏洞&#xff09;是一种由于Web服务器或Web应用程序对用户输入的文件名称的安全性验证不足而导致的安全漏洞。 原理 目录遍历漏洞允许攻击者在未授权…

.NET9 - 新功能体验(三)

书接上回&#xff0c;我们继续来聊聊.NET9和C#13带来的新变化。 01、Linq新方法 CountBy 和 AggregateBy 引入了新的方法 CountBy 和 AggregateBy后&#xff0c;可以在不经过GroupBy 分配中间分组的情况下快速完成复杂的聚合操作&#xff0c;同时方法命名也非常直观&#xff0…

Android蓝牙架构,源文件目录/编译方式学习

Android 版本 发布时间 代号&#xff08;Codename&#xff09; Android 1.0 2008年9月23日 无 Android 1.1 2009年2月9日 Petit Four Android 1.5 2009年4月27日 Cupcake Android 1.6 2009年9月15日 Donut Android 2.0 2009年10月26日 Eclair Android 2.1 2…

YOLO-World解读:零基础学习开放世界模型

文章目录 一、摘要二、引言相关工作方法预训练公式模型架构可重新参数化的视觉-语言路径聚合网络&#xff08;RepVL-PAN&#xff09; 3.4 预训练方案 实验YOLO-World: 利用多样化数据集进行开放词汇对象检测的预训练方法YOLO-World: LVIS数据集上的零样本性能评估YOLO-World: 预…

信创改造 - TongRDS 安装方式之控制台安装【Window】

安装前准备 安装 jdk1.8 即可&#xff0c;并配上 环境变量 安装 1&#xff09;解压缩 2&#xff09;启动 进入安装路径的console\bin目录&#xff0c;在cmd命令行窗口运行console.bat 输入序号 1 如果想查看运行状态&#xff0c;可以重新执行 console.bat&#xff0c;然后输…

志愿者小程序源码社区网格志愿者服务小程序php

志愿者服务小程序源码开发方案&#xff1a;开发语言后端php&#xff0c;tp框架&#xff0c;前端是uniapp。 一 志愿者端-小程序&#xff1a; 申请成为志愿者&#xff0c;志愿者组织端进行审核。成为志愿者后&#xff0c;可以报名参加志愿者活动。 志愿者地图&#xff1a;可以…

Node.js的下载与安装(支持各种新旧版本)

目录 1、node官网 2、node软件下载 3、软件安装&#xff08;完整版&#xff09; 1、node官网 Node.js — Download Node.jshttps://nodejs.org/en/download/package-manager 2、node软件下载 按照下图进行选择node版本&#xff08;真心推荐16/18&#xff0c;而是尽量是LTS…