【设计模式】-工厂模式

工厂模式是一种创建型设计模式,它提供了一种在不指定具体类的情况下创建对象的方法。工厂模式的核心思想是将对象的创建与使用分离,降低系统的耦合度,使系统更加灵活、可扩展。

工厂模式主要分为三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。下面我将分别介绍这三种工厂模式,并给出相应的Java实例代码。

三种模式介绍

1. 简单工厂模式

简单工厂模式又称为静态工厂方法模式,它由一个工厂类根据传入的参数决定创建哪一种产品类的实例。
在这里插入图片描述

Java实例代码:

// 产品接口
public interface Car {void drive();
}// 具体产品类1
public class BMW implements Car {@Overridepublic void drive() {System.out.println("Driving BMW");}
}// 具体产品类2
public class Benz implements Car {@Overridepublic void drive() {System.out.println("Driving Benz");}
}// 工厂类
public class CarFactory {public static Car createCar(String type) {if ("BMW".equalsIgnoreCase(type)) {return new BMW();} else if ("Benz".equalsIgnoreCase(type)) {return new Benz();} else {throw new IllegalArgumentException("Invalid car type: " + type);}}
}// 客户端代码
public class Client {public static void main(String[] args) {Car bmw = CarFactory.createCar("BMW");bmw.drive();Car benz = CarFactory.createCar("Benz");benz.drive();}
}

2. 工厂方法模式

工厂方法模式将对象的创建延迟到子类中进行,工厂类不再负责具体产品的创建,而是提供一个创建产品的抽象方法,由子类实现具体的创建逻辑。
在这里插入图片描述

Java实例代码:

// 产品接口
public interface Car {void drive();
}// 具体产品类1
public class BMW implements Car {@Overridepublic void drive() {System.out.println("Driving BMW");}
}// 具体产品类2
public class Benz implements Car {@Overridepublic void drive() {System.out.println("Driving Benz");}
}// 工厂接口
public interface CarFactory {Car createCar();
}// 具体工厂类1
public class BMWFactory implements CarFactory {@Overridepublic Car createCar() {return new BMW();}
}// 具体工厂类2
public class BenzFactory implements CarFactory {@Overridepublic Car createCar() {return new Benz();}
}// 客户端代码
public class Client {public static void main(String[] args) {CarFactory bmwFactory = new BMWFactory();Car bmw = bmwFactory.createCar();bmw.drive();CarFactory benzFactory = new BenzFactory();Car benz = benzFactory.createCar();benz.drive();}
}

3. 抽象工厂模式

抽象工厂模式(Abstract Factory Pattern)提供了一种方式来封装一组具有共同主题的单个工厂,而不需要指定它们的具体类。客户端使用抽象工厂来创建一系列的相关或相互依赖的对象,而不需要指定它们具体的类。这样可以将客户端与具体产品的创建分离,使得系统更易于扩展和维护。
在这里插入图片描述

下面是一个简单的Java代码实例,展示了抽象工厂模式的应用:

// 抽象产品A
public interface Gui {void draw();
}// 具体产品A1
public class WinGui implements Gui {@Overridepublic void draw() {System.out.println("Drawing Windows GUI");}
}// 具体产品A2
public class MacGui implements Gui {@Overridepublic void draw() {System.out.println("Drawing MacOS GUI");}
}// 抽象产品B
public interface Button {void click();
}// 具体产品B1
public class WinButton implements Button {@Overridepublic void click() {System.out.println("Clicking Windows Button");}
}// 具体产品B2
public class MacButton implements Button {@Overridepublic void click() {System.out.println("Clicking MacOS Button");}
}// 抽象工厂
public interface UiFactory {Gui createGui();Button createButton();
}// 具体工厂1
public class WinUiFactory implements UiFactory {@Overridepublic Gui createGui() {return new WinGui();}@Overridepublic Button createButton() {return new WinButton();}
}// 具体工厂2
public class MacUiFactory implements UiFactory {@Overridepublic Gui createGui() {return new MacGui();}@Overridepublic Button createButton() {return new MacButton();}
}// 客户端代码
public class Client {public static void main(String[] args) {// 使用Windows风格的UI组件UiFactory winFactory = new WinUiFactory();Gui winGui = winFactory.createGui();Button winButton = winFactory.createButton();winGui.draw();winButton.click();// 使用MacOS风格的UI组件UiFactory macFactory = new MacUiFactory();Gui macGui = macFactory.createGui();Button macButton = macFactory.createButton();macGui.draw();macButton.click();}
}

在这个例子中,我们定义了两个抽象产品:GuiButton,分别代表图形用户界面和按钮。然后,我们为每种操作系统(Windows和MacOS)创建了具体的产品实现。WinGuiMacGuiGui 的具体实现,而 WinButtonMacButtonButton 的具体实现。

我们定义了一个抽象工厂接口 UiFactory,它包含了创建 GuiButton 的方法。然后,我们为每种操作系统创建了一个具体的工厂实现:WinUiFactoryMacUiFactory。这些工厂负责创建对应操作系统的具体产品实例。

在客户端代码中,我们可以根据需要选择使用哪种风格的UI组件。通过创建不同风格的工厂实例,并调用其创建方法,我们可以得到对应风格的 GuiButton 对象,并调用它们的方法。这样,客户端代码与具体产品的创建逻辑被完全分离,提高了系统的灵活性和可维护性。

对比

是不是还有点晕,好像“工厂方法模式”和“抽象工厂模式”傻傻分不清楚啊。那我们来张表对比一下,就清晰了:

特性/模式简单工厂模式工厂方法模式抽象工厂模式
结构一个工厂类负责创建所有产品抽象工厂类定义接口,具体工厂类负责创建对应产品抽象工厂类定义创建产品族的接口,具体工厂类负责创建多个具体产品
扩展性不符合“开闭原则”,新增产品需修改工厂类符合“开闭原则”,新增产品只需添加新类和工厂子类新增产品族符合“开闭原则”,单独新增产品不符合
使用场景产品种类少且不常变动产品种类多且经常变动需要创建一系列相互关联或依赖的产品
责任划分工厂类负责创建所有产品实例具体工厂子类负责创建对应产品实例具体工厂子类负责创建多个相互关联的产品实例
客户端与产品创建客户端直接调用工厂类创建产品客户端通过工厂子类接口创建产品客户端通过工厂子类接口创建多个相关产品
灵活性较低,工厂类集中了所有产品创建逻辑较高,产品创建逻辑分散在工厂子类中较高,可以灵活创建多个相关产品
代码复杂性较低,结构简单中等,需要定义抽象工厂和具体工厂类较高,涉及多个抽象产品类和具体产品类

了解下“产品族”是个啥:
在这里插入图片描述
在抽象工厂模式中,产品族是指由同一个工厂生产的,位于不同产品等级结构中的一组产品。这些产品虽然在类型上有所差异,但它们在功能上是相互关联或依赖的。

为了更好地理解这个概念,我们可以以一个实际的例子来说明。假设有一个电器制造工厂,它生产了电视机和电冰箱两种产品。这两种产品分别属于不同的产品等级结构:电视机有其自己的产品等级结构,包括不同品牌、型号的电视机;电冰箱也有其独立的产品等级结构,涵盖了各种类型、规格的电冰箱。然而,在这个例子中,由于它们都是由同一个电器制造工厂生产的,因此电视机和电冰箱构成了一个产品族。

这个产品族中的每个成员(即电视机和电冰箱)都有其特定的功能和用途,但它们都是电器制造工厂的产品,共享了相同的生产标准和质量控制体系。因此,它们在功能上是相互关联或依赖的,构成了一个有机的整体。

抽象工厂模式通过提供一个接口,使得客户端可以创建一系列相关或相互依赖的对象,而无需指定它们具体的类。在上面的例子中,客户端可以通过调用电器制造工厂的接口,一次性地获取到电视机和电冰箱这两种产品,而无需关心它们具体的实现细节。

这下是不是就清晰了。OVER。

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

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

相关文章

#Ubuntu(修改root信息)

(一)发行版:Ubuntu16.04.7 (二)记录: (1)命令行终端: a.右键,open terminal b.快捷键 ctrlaltt (2)进行root修改 sudo passwd &a…

【推荐系统】NCF神经协同过滤

NCF框架 NCF框架是本文要实现的3个模型的主体结构。 首先是输入层,分别包含两个特征向量 v u v_u vu​和 v i v_i vi​,描述了用户u和物品i。输入仅由一个用户向量和一个物品向量构成,它们分别是以one-hot编码的二值化稀疏向量。 接着是Em…

[HNCTF 2022 WEEK2]e@sy_flower

获取基本信息 获取关键字符串 进来“开门红” 上一篇博客才发现这个 按u转换为二进制 有个无效db,最简单的花指令 nop掉 重新u一下p一下 就正常了 然后编译完main函数 int __cdecl __noreturn main(int argc, const char **argv, const char **envp) {signed in…

Python深度学习技术教程

原文链接:Python深度学习技术教程https://mp.weixin.qq.com/s?__bizMzUzNTczMDMxMg&mid2247597949&idx4&sn65c0d353d02b060fec98ec799f217ae1&chksmfa823e9acdf5b78cd71cfcb060e3b60125b17afbe3e19ef423d4709d2df7fc93d90ce3097253&token14787…

Unity InputField实现框自适应内容简便方法

要实现InputField框自适应输入内容,除了通过代码进行处理,还可以是使用以下简便的方法。 1、创建InputField组件:右键->UI->Input Field -TextMeshPro。 2、把Input Field Settings中的Line Type设置为Multi Line Newline模式&#x…

Jenkins + Docker + ASP.NET Core自动化部署

本来没想着要写这篇博客,但是在实操过程中,一个是被网络问题搞炸了心态(真心感觉网络能把人搞疯,别人下个包、下个镜像几秒钟搞定,我看着我的几KB小水管真是有苦说不出),另一个就是这里面坑还是…

【Java】高级篇1:异常处理

异常:程序在执行过程中出现的非正常情况,如果不处理最终会导致JVM的非正常停止。 Java的异常抛出机制 Java异常体系 1、Throwable 2、Error和Exception 异常处理方式 1、try-catch-finally(捕获异常) 基本结构: 使用…

Day68:WEB攻防-Java安全原生反序列化SpringBoot攻防heapdump提取CVE

目录 Java安全-反序列化-原生序列化类函数 原生序列化类函数 SnakeYaml XMLDecoder ObjectInputStream.readObject 工具利用 ysoserial Yakit SerializedPayloadGenerator Java安全-SpringBoot框架-泄漏&CVE SpringBoot Actuator-黑白盒发现 人工识别 BurpSui…

数据库事务中“锁”的分类

数据库事务中的锁可以按照不同的维度进行分类。以下是一些常见的分类方式: 1、按锁的粒度分类: 行锁(Row-level lock):锁定单个或少量的数据行。这种锁粒度小,允许高度的并发,但管理开销大。页…

LeetCode 2312.卖木头块:动态规划(DP)

【LetMeFly】2312.卖木头块:动态规划(DP) 力扣题目链接:https://leetcode.cn/problems/selling-pieces-of-wood/ 给你两个整数 m 和 n ,分别表示一块矩形木块的高和宽。同时给你一个二维整数数组 prices ,其中 prices[i] [hi, …

LeetCode118 杨辉三角形

题目 给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中,每个数是它左上方和右上方的数的和。 示例 示例 1: 输入: numRows 5 输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]示例 2: 输入: numRows 1 输出: [[1]] 解…

汽车电子拓扑架构的演进过程

汽车电子拓扑架构的演进过程 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师 (Wechat:gongkenan2013)。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 本就是小人物,输了就是输了,不要在意别人怎么看自己。江湖一碗茶,喝完再挣扎,出门靠…

Python 常用的开源爬虫库介绍

Python 是一种广泛使用的编程语言,特别是在 Web 爬虫领域。有许多优秀的开源爬虫库可以帮助开发者高效地抓取网页内容。以下是几个常用的 Python 爬虫库及其特点和优势: BeautifulSoup 特点 - **HTML/XML 解析**:BeautifulSoup 是一个…

linux(Ubuntu22) 一篇带你学会Linux,详细篇

Linux 简介 精通Linux,自带python,系统开源 电脑可安装双系统 c盘安装win D盘安装linux 在一套硬件上只能同时运行一个操作系统 虚拟机 模拟真实环境 在虚拟机内运行操作系统 需要硬件支持虚拟化 开启VT-X VM…

opengl程序错误,无法定位程序输入点 glewGetErrorString@4 于动态链接库

使用mingw编译器编译运行opengl程序,编译通过运行时崩溃 怀疑是之前的mingw版本编译的glew库版本不对,又重新编译一遍,还是这个错误 之后检查环境变量配置,发现有两个glew的路径,一个是msvc版的,另一个是m…

Unity WebGL服务器标头的问题

目录 现象: 报错文本: 原因: 解决方案: 现象: 打包前,ProjectSetting 压缩选项设置为Brotli, 将打包的WebGL部署到阿里云OSS环境后,运行弹框提示错误. 报错文本: Unable to parse Build/WebGL.framework.js.br! This canha…

三级等保技术建议书

1信息系统详细设计方案 1.1安全建设需求分析 1.1.1网络结构安全 1.1.2边界安全风险与需求分析 1.1.3运维风险需求分析 1.1.4关键服务器管理风险分析 1.1.5关键服务器用户操作管理风险分析 1.1.6数据库敏感数据运维风险分析 1.1.7“人机”运维操作行为风险综合分析 1.2…

QT----基于QT的人脸考勤系统

目录 1 编译opencv库1.1 下载源代码1.2 qt编译opencv1.3 执行Cmake一直卡着data: Download: face_landmark_model.dat 2 编译SeetaFace2代码2.1 遇到报错By not providing "FindOpenCV.cmake" in CMAKE_MODULE_PATH this project has2.2遇到报错Model missing 3 测试…

web高可用集群(nginx负载均衡+keepalived实现调度器HA)

web高可用集群(nginx负载均衡keepalived实现调度器HA) 主机IP地址代理服务器192.168.88.66代理服务器192.168.88.38Real server192.168.88.10Real server192.168.88.20 配置俩台Real server [rootweb1 ~]# vim /etc/yum.repos.d/nginx.repo [rootweb1 ~]# cat /e…

KT6368A蓝牙主从一体芯片_功能简要说明

一、功能简介 新增KT1328A芯片方案的蓝牙主从一体版本,实现的是主从一体相互切换,也就是说可以设置为主机【类似于手机的角色】,也可以设置为从机角色,通过AT指令 此版本的型号命名为:KT1328A-SOP8 。后续需要下单…