设计模式——三大工厂模式

工厂模式

简单工厂模式(静态工厂模式)

介绍:

1、简单工厂模式是属于创建型模式,是工厂模式的一种,**简单工厂模式是由一个工厂对象决定创建出哪种产品的实例**。是工厂模式中最简单使用的模式
2、简单工厂模式:定义了一个创建对象的类,由这个类封装实例化对象的行为(代码)
3、在软件开发中,当我们会用到大量的创建某种、某类或者某批对象时,就会使用到工厂模式。

public interface Shape {void draw();
}
​
public class Circle implements Shape {@Overridepublic void draw() {System.out.println("绘制一个圆形");}
}
​
public class Rectangle implements Shape {@Overridepublic void draw() {System.out.println("绘制一个矩形");}
}
​
public class Square implements Shape {@Overridepublic void draw() {System.out.println("绘制一个正方形");}
}
​
​
public class ShapeFactory {public static Shape createShape(String type) {if (type.equalsIgnoreCase("circle")) {return new Circle();} else if (type.equalsIgnoreCase("rectangle")) {return new Rectangle();} else if (type.equalsIgnoreCase("square")) {return new Square();}return null;}
}
​
​
public class Main {public static void main(String[] args) {Shape circle = ShapeFactory.createShape("circle");circle.draw();  // 输出:绘制一个圆形
​Shape rectangle = ShapeFactory.createShape("rectangle");rectangle.draw();  // 输出:绘制一个矩形
​Shape square = ShapeFactory.createShape("square");square.draw();  // 输出:绘制一个正方形}
}
总结:
优点:
​
1、简单工厂模式实现了对象创建和对象使用的分离,客户端只需知道产品的类型,无需关心产品的创建细节。
2、可以通过工厂方法来集中控制对象的创建,便于统一管理和维护。
3、客户端可以直接通过工厂类来创建对象,简化了客户端代码,提高了代码的可读性和可维护性。
4、简单工厂模式实现了依赖倒置原则,客户端只需要依赖工厂类,而不需要依赖具体的产品类,降低了耦合
​
​
缺点:
​
1、当需要新增产品时,需要修改工厂类的代码,违反了开闭原则。
2、工厂类的职责较重,包括对象的创建和选择逻辑,违反了单一职责原则。
3、对象的创建过程集中在一个工厂类中,如果系统中的产品过多或产品创建过程复杂,会导致工厂类臃肿,不利于扩展和维护。
4、简单工厂模式会导致客户端与工厂类之间的耦合度增加,一旦工厂类出现问题,客户端可能也会受到影响。
​
​
总的来说,简单工厂模式适用于对象较少且变化不频繁的场景,但在面对频繁变化的产品类型或产品创建过程复杂的情况下,不太适合使用简单工厂模式。

工厂方法模式

介绍

定义了一个创建对象的抽象方法,由子类决定要实例化的累。工厂方法模式将对象的实例化放到子类。(子类进行生产对象)
// 抽象产品类
interface Product {void operation();
}
​
// 具体产品类A
class ConcreteProductA implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductA operation");}
}
​
// 具体产品类B
class ConcreteProductB implements Product {@Overridepublic void operation() {System.out.println("ConcreteProductB operation");}
}
​
// 工厂接口
interface Factory {Product createProduct();
}
​
// 具体工厂A
class ConcreteFactoryA implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductA();}
}
​
// 具体工厂B
class ConcreteFactoryB implements Factory {@Overridepublic Product createProduct() {return new ConcreteProductB();}
}
​
// 客户端代码
public class Client {public static void main(String[] args) {Factory factoryA = new ConcreteFactoryA();Product productA = factoryA.createProduct();productA.operation();
​Factory factoryB = new ConcreteFactoryB();Product productB = factoryB.createProduct();productB.operation();}
}
优点: 1、松耦合:工厂方法模式将客户端代码与具体产品类解耦,客户端不需要知道具体产品的类名,只需要知道产品的接口或抽象类即可。这使得系统更容易维护和扩展,因为新增产品时只需添加新的具体产品类和对应的工厂类,而不需要修改现有的客户端代码。 ​ 2、可扩展性:由于每个具体产品都有对应的具体工厂,可以轻松地添加新的具体产品类和对应的工厂类,而不会影响现有的代码结构。这使得系统具有很好的可扩展性,符合开闭原则。 ​ 3、封装变化:工厂方法模式将对象的创建过程封装到具体的工厂类中,客户端无需关心对象的创建细节,只需通过工厂来获取对象。这样,如果对象的创建过程发生变化,只需修改对应的工厂类,而不会影响客户端代码。 ​ 缺点: 1、类的数量增加:工厂方法模式会导致系统中类的数量增加,因为每个具体产品都需要对应一个具体工厂。如果产品种类很多,会导致类的数量剧增,增加了系统的复杂度。 ​ 2、增加了系统的抽象性和理解难度:引入了抽象工厂和具体工厂的概念,增加了系统的抽象性,使得系统的理解和学习成本增加。 ​ 3、一定程度上增加了开发的复杂度:相对于简单的直接实例化对象来说,工厂方法模式引入了额外的抽象层,增加了开发的复杂度,尤其是对于简单的场景来说可能会显得过于繁琐。 ​ 工厂方法模式的优点包括松耦合、可扩展性和封装变化。它将客户端代码与具体产品类解耦,使系统更易于维护和扩展。缺点包括增加类的数量、增加系统的抽象性和理解难度,以及在一定程度上增加了开发的复杂度。在设计时需要权衡利弊,根据具体情况选择是否使用工厂方法模式

抽象工厂模式

介绍:

1、抽象工厂模式:它提供了一个接口,用于创建相关或依赖对象的家族,而无需指定具体类。
-》 说明抽象工厂模式允许客户端使用抽象的接口来创建相关的产品对象,并且不需要知道具体实现
​
2、将工厂抽象成两层,AbsFactory(抽象工厂)和具体实现的工厂子类。我们可以根据创建类型和使用对应的工厂子类,将单个的简单工厂类变成工厂家族,利于代码的维护和扩展

这是一个类图:

抽象工厂就是有一个总的抽象工厂类,然后有子类去实现这个抽象工厂来实现它,并且为之实现生产产品的方法

定义抽象工厂 PizzaFactory 和抽象产品接口 Pizza 以及原料接口 PizzaIngredient:// 抽象工厂
interface PizzaFactory {Pizza createPizza();PizzaIngredient createIngredient();
}
​
// 抽象产品 - 披萨
interface Pizza {void prepare();void bake();void cut();void box();
}
​
// 抽象产品 - 原料
interface PizzaIngredient {String getIngredient();
}
​
这里是实现具体的工厂类和产品类:// 具体工厂类 - 纽约风味披萨工厂
class NYPizzaFactory implements PizzaFactory {@Overridepublic Pizza createPizza() {return new NYStylePizza();}
​@Overridepublic PizzaIngredient createIngredient() {return new NYStyleIngredient();}
}
​
// 具体工厂类 - 芝加哥风味披萨工厂
class ChicagoPizzaFactory implements PizzaFactory {@Overridepublic Pizza createPizza() {return new ChicagoStylePizza();}
​@Overridepublic PizzaIngredient createIngredient() {return new ChicagoStyleIngredient();}
}
​
// 具体产品类 - 纽约风味披萨
class NYStylePizza implements Pizza {// 省略具体实现
}
​
// 具体产品类 - 芝加哥风味披萨
class ChicagoStylePizza implements Pizza {// 省略具体实现
}
​
// 具体产品类 - 纽约风味原料
class NYStyleIngredient implements PizzaIngredient {@Overridepublic String getIngredient() {return "NY style ingredient";}
}
​
// 具体产品类 - 芝加哥风味原料
class ChicagoStyleIngredient implements PizzaIngredient {@Overridepublic String getIngredient() {return "Chicago style ingredient";}
}
​
// 客户端代码
public class PizzaStore {private PizzaFactory factory;
​public PizzaStore(PizzaFactory factory) {this.factory = factory;}
​public Pizza orderPizza() {Pizza pizza = factory.createPizza();PizzaIngredient ingredient = factory.createIngredient();System.out.println("Preparing " + pizza.getClass().getSimpleName() + " with " + ingredient.getIngredient());pizza.prepare();pizza.bake();pizza.cut();pizza.box();return pizza;}
​public static void main(String[] args) {PizzaStore nyStore = new PizzaStore(new NYPizzaFactory());nyStore.orderPizza();
​PizzaStore chicagoStore = new PizzaStore(new ChicagoPizzaFactory());chicagoStore.orderPizza();}
}

抽象工厂模式是一种创建型设计模式,它提供了一种封装一组相关对象创建的方式。
​
优点:
抽象工厂模式通过解耦具体类的创建与客户端代码,确保产品系列相互匹配,并容易交换不同产品系列
​
​
缺点:
​
增加新的产品族或产品等级结构可能导致抽象工厂接口和具体工厂类的修改,以及需要修改所有客户端代码。

小结

工厂模式在JDK-Calendar应用的源码:使用到了简单工厂模式

1、工厂模式的目的:

将实例化对象的代码提取出来,放到一个类中统一管理和维护,达到和主项目的依赖关系的解耦。从而提高项目的扩展和维护性。

2、三种工厂模式

- 简单工厂模式:由一个工厂类根据客户端请求创建产品,适用于产品种类较少且变化不频繁的情况。
​​
- 工厂方法模式:定义创建对象接口,延迟具体创建到子类实现,允许系统引入新产品而不修改客户端代码。
​​
- 抽象工厂模式:提供接口创建相关对象,通过具体工厂创建产品族,适用于创建相互关联或依赖对象的情况。

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

使用ffmpeg实现视频片段截取并保持清晰度

1 原始视频信息 通过ffmpeg -i命令查看视频基本信息 ffmpeg -i input.mp4 ffmpeg version 6.1-essentials_build-www.gyan.dev Copyright (c) 2000-2023 the FFmpeg developersbuilt with gcc 12.2.0 (Rev10, Built by MSYS2 project)configuration: --enable-gpl --enable-ve…

HTB pwn Dragon Army

逆向分析 程序使用了alloca函数扩大了栈区 此处可以泄露libc的地址 程序主要功能在下面 while ( 1 ){while ( 1 ){fflush(stdin);fflush(_bss_start);fprintf(_bss_start, "\n%sDragons: [%d/%d]%s\n\n", "\x1B[1;34m", v5, 13LL, "\x1B[1;37m"…

RLE 稀疏水平集 RLE sparse level sets 论文阅读笔记

目录 RLE 稀疏水平集随机访问水平集游程类型编码CSG 操作增强水平集 表现动画角色网格面到 RLE 水平集自相交时间抗锯齿 总结 原文: Houston, Ben, Mark Wiebe, and Chris Batty. “RLE sparse level sets.” ACM SIGGRAPH 2004 Sketches. 2004. 137. 只有一页&am…

【Java】RestClient的使用

RestClient的使用 先导入Maven坐标&#xff0c;要和elasticsearch和kibana的版本保持一致 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.12.1<…

【深度学习】LoRA: Low-Rank Adaptation of Large Language Models,论文解读

文章&#xff1a; https://arxiv.org/abs/2106.09685 文章目录 摘要介绍LoRA的特点什么是低秩适应矩阵&#xff1f;什么是适应阶段&#xff1f;低秩适应矩阵被注入到预训练模型的每一层Transformer结构中&#xff0c;这一步是如何做到的&#xff1f; 摘要 自然语言处理的一个重…

c# 类的介绍及延伸

类介绍 类的定义是以关键字 class 开始&#xff0c;后跟类的名称。 类属于引用类型&#xff0c;只能通过new方式创建。 如果类定义中没有指定基类&#xff0c;那其基类为system.object // <访问修饰符> class class类名 <access specifier> class class_name { //…

Math.random、Random随机数的生成

Math.random、Random随机数的生成 Math.random() 方法案例&#xff1a;生成随机整数案例&#xff1a;生成随机字符 Random()类Random生产区间随机数的技巧&#xff1a;减加法案例&#xff1a;猜测随机一个幸运号码 1 - 100案例&#xff1a;生成随机字符 Math.random() 方法 Ma…

数据价值在线化丨TiDB 在企查查数据中台的应用及 v7.1 版本升级体验

本文介绍了企查查在数据中台建设中使用 TiDB 的经验和应用。通过从 MySQL 到 TiDB 的迁移&#xff0c;企查查构建了基于 TiDB Flink 的实时数仓框架 &#xff0c;充分利用了 TiDB 的分布式架构、MySQL 兼容性和完善的周边工具等特性&#xff0c;实现了数据的在线化处理。2023 年…

ACM题解Day6 | 质数素数模块 | 完数难题

学习目标&#xff1a; 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门算法 &#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d; ☆*: .&#xff61;. o(≧▽…

Vue模板引用之ref特殊属性

1. 使用实例 <template><input ref"input" name"我是input的name" /><br /><ul><li v-for"arr in array" :key"arr" id"111" ref"itemRefs">{{arr}}</li></ul> </…

较通用web脚手架模板搭建

较通用web脚手架模板搭建 从这里开始就接触到以后写项目的思维了。 做一个web开发&#xff0c;那就要层次分明&#xff0c;要有个实现的规划&#xff0c;这通常也是有一个较为通用的模板的。 总的来说&#xff1a;不同的层次有不同的模块&#xff0c;每个模块有必须实现的功…

常用!基础!吴恩达deeplearning.ai:Tensorflow中数据形式

由于一些历史遗留问题&#xff0c;Numpy和Tensorflow在数据处理方面存在一些不一致的地方&#xff0c;今天我们主要来了解一下其中一些约定俗成的形式&#xff0c;从而能够让你写出正确的代码(耍帅&#xff09;。 文章目录 Tensorflow是如何表示数据的特征向量关于Numpy矩阵激…

Flutter(一):安装和环境配置、创建Flutter项目

安装和环境配置、创建Flutter项目 Flutter 下载方式1方式2 Flutter 环境配置配置国内镜像站点解压 Flutter将 flutter 添加到系统环境变量中运行 flutter doctor来验证安装 Android Studio下载插件创建项目安装 Android SDK 工具在模拟器上运行 Flutter 下载 方式1 全版本&…

深度学习介绍与环境搭建

深度学习介绍与环境搭建 慕课大学人工智能学习笔记&#xff0c;自己学习记录用的。&#xff08;赋上连接&#xff09; https://www.icourse163.org/learn/ZUCC-1206146808?tid1471365447#/learn/content?typedetail&id1256424053&cid1289366515人工智能、机器学习与…

数据结构day4

实现创建单向循环链表、创建结点、判空、输出、头插、按位置插入、尾删、按位置删除 loop_list.c #include "loop_list.h" loop_p create_head() {loop_p L(loop_p)malloc(sizeof(loop_list));if(LNULL){printf("空间申请失败\n");return NULL;}L->le…

华为配置WLAN AC和AP之间VPN穿越示例

配置WLAN AC和AP之间VPN穿越示例 组网图形 图1 配置WLAN AC和AP之间VPN穿越示例组网图 业务需求组网需求数据规划配置思路配置注意事项操作步骤配置文件 业务需求 企业用户接入WLAN网络&#xff0c;以满足移动办公的最基本需求。且在覆盖区域内移动发生漫游时&#xff0c;不影响…

CentOS 7.9.2009离线安装mysql 8.0客户端 (rpm包)

环境&#xff1a; #需求&#xff1a; 该服务器需要将csv文件入库到远端的mysql 服务器上。 CentOS Linux release 7.9.2009 (Core) 离线环境 &#xff0c;需安装mysql客户端 8.0.27#下载地址 https://downloads.mysql.com/archives/community/#按此顺序安装 rpm -ivh mysql…

alist修改密码(docker版)

rootarmbian:~# docker exec -it [docker名称] ./alist admin set abcd123456 INFO[2024-02-20 11:06:29] reading config file: data/config.json INFO[2024-02-20 11:06:29] load config from env with prefix: ALIST_ INFO[2024-02-20 11:06:29] init logrus..…

Kotlin filterIsInstance filterNotNull forEach

Kotlin filterIsInstance filterNotNull forEach fun main(args: Array<String>) {val i1 MyItem(1, 1)val i2: MyItem? nullval i3: Int 3val i4 "4"val i5 nullval i6 MyItem(6, 6)val list mutableListOf<Any?>(i1, i2, i3, i4, i5, i6)lis…

【算法与数据结构】链表、哈希表、栈和队列、二叉树(笔记二)

文章目录 四、链表理论五、哈希表理论五、栈和队列理论5.1 单调栈 六、二叉树理论6.1 树的定义6.2 二叉树的存储方式6.3 二叉树的遍历方式6.4 高度和深度 最近博主学习了算法与数据结构的一些视频&#xff0c;在这个文章做一些笔记和心得&#xff0c;本篇文章就写了一些基础算法…