【设计模式】-工厂模式

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

工厂模式主要分为三种类型:简单工厂模式、工厂方法模式和抽象工厂模式。下面我将分别介绍这三种工厂模式,并给出相应的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…

【LeetCode周赛】第 389 场周赛

目录 3083. 字符串及其反转中是否存在同一子字符串 简单3084. 统计以给定字符开头和结尾的子字符串总数 中等3085. 成为 K 特殊字符串需要删除的最少字符数 中等3086. 拾起 K 个 1 需要的最少行动次数 困难 3083. 字符串及其反转中是否存在同一子字符串 简单 3083. 字符串及其…

程序员快速自我提升法——鱼皮大佬

0 软件开发人员自我成长 1 每天读2~3篇文章,可以行业趋势、技术类(和自己的工作有关的) 大厂技术博客科技资讯类:量子位、差评、新智元、无敌信息差 量子位、新智元经验分享、编程趋势、技术干活:程序员鱼皮、小林coding、java guide、程序…

【推荐系统】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…

机器学习算法大全(MLS-C01)

算法名字监督学习简介和用途协同过滤是推荐算法Factorization Machines algorithm否推荐算法,准确度更高,不会误打扰。KNN否利用已知样本,找最邻近的样本的分类算法K-means否聚类算法RCF否异常检测Latent Dirichlet Allocation否主题提取和文…

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小水管真是有苦说不出),另一个就是这里面坑还是…

5. 最长回文子串

5. 最长回文子串 中等 相关标签 相关企业 提示 给你一个字符串 s,找到 s 中最长的回文 子串 。 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。 示例 1: 输入:s "babad" 输出:&quo…

2024.2.28 校招 实习 内推 面经

绿*泡*泡VX: neituijunsir 交流*裙 ,内推/实习/校招汇总表格 1、校招 | OPPO流程IT团队 校招扩招 (内推) 校招 | OPPO流程IT团队 校招扩招 (内推) 2、校招 | 顺丰集团2024届春季校园招聘正式启动&#…

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

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

算法笔记p328_并查集

目录 并查集的定义并查集的基本操作初始化查找合并 路径压缩 并查集的定义 并查集是一种维护集合的数据结构,支持下面两个操作: 合并:合并两个集合。查找:判断两个元素是否在一个集合。 并查集用一个数组实现: int…

OpenJudge - 12:计算2的N次方

总时间限制: 1000ms 内存限制: 65536kB 描述 任意给定一个正整数N(N<100)&#xff0c;计算2的n次方的值。 输入 输入一个正整数N。 输出 输出2的N次方的值。 样例输入 5 样例输出 32 关键代码 #include<stdio.h> int main() {int n,a[51] {0},c[51] {0},count 0…

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

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

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

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

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

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

【蓝桥杯】蓝桥杯嵌入式——题目总结及文章汇总(内含客观题与主观题,并且都附有详细题解)

介绍 蓝桥杯嵌入式比赛是一项专注于嵌入式开发的全国性比赛&#xff0c;旨在鼓励和促进嵌入式系统的研究和应用&#xff0c;提高嵌入式开发的水平和技能。 比赛分为初赛和复赛两个阶段。初赛难度适中&#xff0c;注重考查参赛选手的嵌入式系统开发能力和实践经验。复赛则采用线…

LeetCode118 杨辉三角形

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

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

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