设计模式-工厂模式设计与详解

一、设计模式介绍

设计模式是我们开发中常常需要面对的核心概念,它们是解决特定问题的模板或者说是经验的总结。这些模式被设计出来是为了让软件设计更加清晰、代码更加可维护且能应对未来的变化。良好的设计模式不仅能解决重复代码的问题,还能使团队中的每个成员都能理解并遵循统一的开发方式。

使用良好的设计模式可以显著提高软件项目的质量和开发效率。它们帮助开发者抽象复杂度,通过预定义的架构方式简化系统结构的设计和实现。设计模式还提供了一种通用语言,使得开发者在讨论架构问题时能够迅速地达成共识,同时确保代码的健壁性和可扩展性。不论是在创建对象、组织复杂的类结构,还是处理类与类之间的关系时,设计模式都提供了有效的管理和优化策略,使得软件更加稳健,易于管理和扩展。

下面是常见的 23 种设计模式:

在这里插入图片描述

本文详细介绍了设计模式中的工厂模式,旨在为软件开发人员提供清晰的理解和应用指南。工厂模式是一种创建型设计模式,用于在不直接指定具体类的情况下创建对象,从而增强代码的灵活性和可扩展性。我们探讨了工厂模式的三种主要形式:简单工厂模式、工厂方法模式和抽象工厂模式。每种模式都通过其结构、代码示例和类图进行了解释,以展示它们在实际开发中如何减少系统的依赖性、提高可维护性和支持易变需求。此外,本文还讨论了每种模式的优势、适用场景以及它们在现实世界软件开发中的实际应用,帮助开发者在面对不同的编程挑战时,能选择合适的模式以优化设计和实现过程。


二、工厂模式概述

工厂模式(Factory Pattern)是一种常用的创建型设计模式,其核心目的是实现创建对象的接口和具体的实例化分离,通过建立一个工厂类,对实现了同一接口的一些类进行实例的创建,以增加系统的灵活性和可维护性。

当需要大量创建一个类的实例的时候,可以使用工厂模式,即从原生的使用类的构造去创建对象的形式迁移到基于工厂提供的方法去创建对象的形式。基于工厂模式的实例创建具有以下好处:

  • 大批量创建对象的时候有统一的入口,易于代码维护;
  • 当发生修改时,仅需修改工厂类的创建方法即可;
  • 符合现实世界的模式,即由工厂来制作产品(对象);

本文将通过类图及示例代码详细介绍工厂模式的三种形式:简单工厂模式工厂方法模式抽象工厂模式

在这里插入图片描述


三、简单工厂模式

简单工厂模式是一种创建型设计模式,它提供了一个创建对象的接口,让其子类决定实例化哪一个类。该模式将对象的创建集中管理,通过专门的工厂类来负责创建所有实例,这样可以避免在客户代码中重复创建对象,降低系统的耦合度,提高模块的可复用性。

1. 简单工厂模式类图

以下类图展示了简单工厂模式的结构:

在这里插入图片描述

在这个类图中,Client 不直接与具体产品类(ConcreteProductAConcreteProductB)交互,而是通过 Factory 类来进行。这样做的优点是客户端从具体产品的创建过程中解耦,提高了程序的扩展性和可维护性。


2. 简单工厂模式示例代码

下面的示例代码进一步阐释了简单工厂模式的应用:

  • 抽象产品:定义了产品的接口,所有的产品都必须实现这个接口。
interface Product {void use();
}
  • 具体产品:实现了产品接口的实体类,定义了具体产品的行为。
class ConcreteProductA implements Product {public void use() {System.out.println("Using ConcreteProductA");}
}class ConcreteProductB implements Product {public void use() {System.out.println("Using ConcreteProductB");}
}
  • 简单工厂:一个工厂类,提供了一个创建对象的方法,客户端通过调用这个方法并传入参数来创建不同的产品实例。
class Factory {public static Product createProduct(String type) {if (type.equals("A")) {return new ConcreteProductA();} else if (type.equals("B")) {return new ConcreteProductB();}return null;}
}
  • 调用简单工厂示例:客户端使用 Factory 类创建具体的产品实例。这种方式的主要优点是工厂类包含必要的逻辑判断,可以决定在运行时创建哪个产品的实例。由于使用了工厂类,客户端可以完全从具体产品的实现中解耦,只需要关心产品的接口。
public class Client {public static void main(String[] args) {Product product = Factory.createProduct("A");product.use();}
}

通过这种方式,简单工厂模式使得新增产品类时,只需要扩展工厂类而不需要修改现有的客户代码,从而增加了系统的灵活性。

也就是将"A"换成其他产品,如果产品类不存在,我们需要新增产品类,同时添加createProduct里type为新产品的情况,其实还是有点麻烦的,所有下面的工厂方法就是对此的改进。


四、工厂方法模式

工厂方法模式是一种创建型设计模式,它提供了一个创建对象的方法,但实际的工作将由子类完成,这样的设计模式可以让类的实例化推迟到其子类中进行。这种模式通过定义一个创建对象的接口,让子类决定实例化哪一个类。工厂方法使一个类的实例化延迟到其子类,从而使代码管理更加简单,同时也扩展了系统的可能功能。

1. 工厂方法模式类图

下面的类图描述了工厂方法模式的结构:

在这里插入图片描述

在这个模式中,Creator 类定义了一个抽象的 factoryMethod(),该方法需要被子类实现以返回一个 Product 类的实例。这样,客户端代码只依赖于 Product 接口,而具体实例化哪个产品类由具体的 Creator 子类决定,这样提高了系统的灵活性和扩展性。


2. 工厂方法模式示例代码

以下示例代码进一步阐释了工厂方法模式的应用:

  • 产品接口:定义了所有具体产品需要实现的接口。
interface Product {void use();
}
  • 具体产品:实现了产品接口的具体类,这些类定义了具体产品的行为。
class ConcreteProductA implements Product {public void use() {System.out.println("Using ConcreteProductA");}
}class ConcreteProductB implements Product {public void use() {System.out.println("Using ConcreteProductB");}
}
  • 抽象创建者:定义了抽象的工厂方法,由具体创建者来实现。
abstract class Creator {abstract Product factoryMethod();
}
  • 具体创建者:继承抽象创建者,实现了工厂方法,决定实际生产的产品。
class ConcreteCreatorA extends Creator {@OverrideProduct factoryMethod() {return new ConcreteProductA();}
}class ConcreteCreatorB extends Creator {@OverrideProduct factoryMethod() {return new ConcreteProductB();}
}
  • 客户端使用:客户端代码通过调用工厂方法来获取产品对象,而无需知道具体的产品类。
public class Client {public static void main(String[] args) {Creator creator = new ConcreteCreatorA();Product product = creator.factoryMethod();product.use();}
}

通过这种方式,工厂方法模式使得添加新产品类时,只需添加一个具体的创建者而无需修改现有代码,符合开闭原则,提高了代码的可维护性和扩展性。

与简单工厂加个产品需要改一揽子的代码相比,工厂方法只需要创建一个新的创建者类,客户端调用时ConcreteCreatorA更换为新类名就可以。


五、抽象工厂模式

抽象工厂模式是创建型设计模式中的一种,它提供了一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类。这种模式是工厂方法模式的一种扩展,它用于创建产品家族,而不仅仅是单一产品。通过这种方式,可以增强程序的灵活性和可维护性,同时也支持良好的封装性和扩展性。

1. 抽象工厂模式类图

以下类图清晰展示了抽象工厂模式的结构和组件之间的关系:

在这里插入图片描述

在这个模式中,AbstractFactory 是一个抽象类,定义了创建一系列产品的接口。每个具体工厂类(如 ConcreteFactory1ConcreteFactory2)实现这个接口,生产具体的产品实例。客户端通过使用工厂接口,而不是直接实例化产品,从而使得具体的产品在客户端保持抽象状态。

2. 抽象工厂模式示例代码

以下示例代码详细说明了抽象工厂模式的实现:

  • 产品接口:定义了产品的操作。
interface AbstractProductA {void use();
}interface AbstractProductB {void use();
}
  • 具体产品:实现产品接口的具体类。
class ConcreteProductA1 implements AbstractProductA {public void use() {System.out.println("Using ConcreteProductA1");}
}class ConcreteProductA2 implements AbstractProductA {public void use() {System.out.println("Using ConcreteProductA2");}
}class ConcreteProductB1 implements AbstractProductB {public void use() {System.out.println("Using ConcreteProductB1");}
}class ConcreteProductB2 implements AbstractProductB {public void use() {System.out.println("Using ConcreteProductB2");}
}
  • 抽象工厂:定义了创建一系列产品的方法。
abstract class AbstractFactory {abstract AbstractProductA createProductA();abstract AbstractProductB createProductB();
}
  • 具体工厂:实现抽象工厂,定义了生产具体产品的方式。
class ConcreteFactory1 extends AbstractFactory {@OverrideAbstractProductA createProductA() {return new ConcreteProductA1();}@OverrideAbstractProductB createProductB() {return new ConcreteProductB1();}
}class ConcreteFactory2 extends AbstractFactory {@OverrideAbstractProductA createProductA() {return new ConcreteProductA2();}@OverrideAbstractProductB createProductB() {return new ConcreteProductB2();}
}
  • 客户端使用:客户端通过抽象工厂接口创建并使用产品。
public class Client {public static void main(String[] args) {AbstractFactory factory = new ConcreteFactory1();AbstractProductA productA = factory.createProductA();AbstractProductB productB = factory.createProductB();productA.use();productB.use();}
}

通过这种方式,抽象工厂模式允许系统在不具体指定产品的情况下创建一系列相关或依赖的对象,支持配置多个工厂,每个工厂创建不同的产品实例,从而增强系统的灵活性和扩展性。

这也是工厂方法模式的升级,虽然在开闭原则上做出了让步,但是为更强的灵活和扩展创造了条件。


六、三种工厂模式异同

首先,我们来看三种工厂模式的定义:

  • 简单工厂模式:最简单的工厂模式,适合产品种类较少且不经常变化的情况。工厂类集中处理所有产品的创建逻辑,这简化了代码但降低了系统的扩展性。
  • 工厂方法模式:允许多个创建者子类来实现具体的产品创建。这种分散的创建过程提高了系统的灵活性,并且增强了代码的可扩展性。
  • 抽象工厂模式:提供一个创建一系列相关或互依赖对象的接口,而无需指定它们具体的类。适用于处理多个系列产品的情况,每个具体工厂都能生产一个完整的产品家族。

在这里插入图片描述

接着,我们用一张表来总结三种工厂模式的特性差异:

特点/模式简单工厂模式工厂方法模式抽象工厂模式
定义提供一个创建对象的接口,由接口决定创建哪一种产品类的实例。定义一个用于创建对象的接口,但由子类决定要实例化的类是哪一个。提供一个接口,用于创建相关的对象家族,而不需要明确指定具体类。
对象创建的责任集中于一个工厂类,通过接收特定参数决定创建对象的类型。分散到多个子类中,每个子类封装了一个产品的创建过程。集中于多个工厂类,每个工厂类负责创建一个产品家族。
实现复杂度
灵活性低,增加新产品需要修改工厂类高,每个产品有其对应的具体工厂类非常高,支持创建产品家族且易于添加新的产品组合
产品扩展性较差,扩展新产品时可能需要修改工厂逻辑好,扩展新产品时仅需添加相应的具体工厂类优,允许通过添加具体工厂和产品类的方式来扩展产品家族
应用场景适用于产品类型数量不多且变动不频繁的情况适用于一个类族有多个变体,但仅需使用其一的情况适用于需要创建多系列产品或产品族,且产品族需要一起使用的情况

通过上述表格,我们可以清晰地看到每种工厂模式的特点及其适用的场景。在不同的开发需求下,我们需要选择最合适的模式。


七、工厂模式的优势与应用场景

1. 工厂模式的优势

优势说明
封装性用户仅需知道产品对应的工厂名,无需关心产品的具体创建细节,从而降低了系统的复杂度。
扩展性新增产品时,只需扩展一个工厂类,而不需修改现有代码,符合开闭原则,易于系统扩展和维护。
解耦分离了产品的实例化过程,使用抽象层促使产品的实现和使用分离,提高了系统的灵活性和可维护性。
代码可维护性由于工厂类和产品类的职责清晰,系统的不同部分可以独立变化而互不影响,从而提高代码的可维护性。

2. 工厂模式的应用场景

  • 当系统中的产品有多于一个的产品族,而系统只消费其中某一产品族时。
  • 当属于同一个产品族的一组产品被设计用于一起使用时,可以使用抽象工厂模式。
  • 当系统需要被配置成一个具有多个不同行为的产品组成时,可以使用工厂模式确保其灵活性和可扩展性。

八、工厂模式总结

工厂模式是设计模式中非常关键的一类,主要用于解决对象创建过程中的复杂性,并帮助将对象的实例化过程与使用者分离,从而增加系统的整体封装性和灵活性。通过定义一个用于创建对象的接口,允许子类决定实例化哪一个类,工厂模式使一个类的实例化延迟到其子类。这种模式不仅帮助管理和维护大型软件系统中的对象创建问题,也使系统更加模块化,易于理解和扩展。总的来说,工厂模式在需要生成复杂对象时,提供了极大的便利和高效的管理与维护策略。

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

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

相关文章

object.key()用法

object.key(obj) 一、概念:返回一个由一个给定对象的自身可枚举属性组成的数组。 二、用法: 1、参数为对象:则返回为 对象属性名组成的数组。 let obj {日期:date,姓名:userName,地址:address}console.log(Object.k…

作业帮重启k12,保底年薪150万。。。

作业帮 近期,一位学而思前员工在脉脉上爆料发问: 收到猎头电话,说作业帮重启 K12,K12 主讲无责保底年薪 150W,base 北京。 楼下评论区一位新东方在职员工表示,似乎有这事儿: 而另外一个网友则表…

WordPress/Typecho 站点使用 CloudFlare 后优化加速方法以及注意事项

目前很多 WordPress 站长都盲目的认为使用了 CloudFlare 后,站点速度明显感觉慢了很多,加上一些别有用心的人(有些人就是这么不喜欢 CloudFlare,你品,你细品!) 再制作一个使用 CloudFlare 站点的测速结果截图,让很多 WordPress 新手站长们谈 CloudFlare 色变。其实大家…

Android Studio开发之路(十)app中使用aar以及报错记录

书接上文:Android Studio开发之路(九)创建android library以及生成aar文件 五、app中使用aar文件的方法 先复制一下上面生成的aar文件。然后在你要添加到的app左上角选择“project”模式,然后找到libs文件夹,点击右键…

#初阶模板

目录 1.泛型编程 2.模板 (1)函数模板 (2)举个栗子(模板的使用) 1.模板的声明有两种形式 2.函数模板的原理 (3)模板参数的匹配原则 (4)类模板 类模板…

探索免费静态IP海外的奥秘

在数字化时代,网络资源的获取和利用对于个人和企业都至关重要。其中,独立静态IP地址更是因其稳定性和安全性备受青睐。本文将带您深入了解“免费的独立静态IP海外”的奥秘,探讨其背后的原理、优势、获取途径以及使用场景。 一、独立静态IP的基…

Kubernetes的Pod控制器深度解析

1.1 Pod控制器介绍 在Kubernetes中,Pod是最小的管理单元,用于运行容器。根据Pod的创建方式,可以将其分为两类: 自主式Pod(Stateless Pods):这些Pod是直接由用户或管理员创建的,通常…

GPT搜索鸽了!改升级GPT-4

最近OpenAI太反常,消息一会一变,直让人摸不着头脑。 奥特曼最新宣布:5月13日开发布会,不是GPT-5,也不是盛传的GPT搜索引擎,改成对ChatGP和GPT-4的升级~ 消息一出,大伙儿都蒙了。 之…

STM32_HAL_系统定时器(SysTick)_实现计时

1介绍 系统定时器(SysTick)是ARM Cortex-M处理器系列中的一个特殊定时器,它不属于STM32F1系列微控制器的外设,而是处理器内部的一个组件。SysTick定时器的作用是为操作系统或其他需要精确时钟计数和中断服务的应用提供基础的时间…

【Linux】自动化构建工具make/Makefile和git介绍

🌈个人主页:秦jh__https://blog.csdn.net/qinjh_?spm1010.2135.3001.5343🔥 系列专栏:https://blog.csdn.net/qinjh_/category_12625432.html 目录 前言 Linux项目自动化构建工具-make/Makefile 举例 .PHONY 常见符号 依赖关系…

05、 java 的三种注释及 javadoc 命令解析文档注释(即:java 特有注释方式)的过程

java的三种注释 1、单行注释:其一、代码展示:其二、特点: 2、多行注释:其一、代码展示:其二、特点: 3、文档注释(java特有):其一、代码展示:其二、注释文档的使用:其三、…

基础ArkTS组件:数据面板组件(图表),日期选择器组件(HarmonyOS学习第三课【3.5】)

tuoz数据面板组件 DataPanel 数据面板组件,用于将多个数据占比情况使用占比图进行展示。 说明 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 无 接口 DataPanel(options:{values: numbe…

开关电源功率测试方法:输入、输出功率测试步骤

在现代电子设备中,开关电源扮演着至关重要的角色,其效率和稳定性直接影响到整个系统的性能。因此,对开关电源进行功率测试成为了电源管理的重要环节。本文将详细介绍如何使用DC-DC电源模块测试系统对开关电源的输入输出功率进行准确测量&…

如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库

前言 作者简介: 懒大王敲代码,计算机专业应届生 今天给大家聊聊如何使用Docker安装并运行Nexus容器结合内网穿透实现远程管理本地仓库,希望大家能觉得实用! 欢迎大家点赞 👍 收藏 ⭐ 加关注哦!&#x1f496…

2024 银行从业资格证考试备考资料及备考群

2024 银行从业资格证考试备考资料 2024 年 06月1、2日 银行从业资格考试全国统一考试(统考) 有没有小伙伴在准备备考的,不知道大家都准备怎么学习呢,这里我整理了一些免费备考资料,含【三色笔记】,供大家…

Spring解决泛型擦除的思路不错,现在它是我的了。

你好呀,我是浮生。 Spring 的事件监听机制,不知道你有没有用过,实际开发过程中用来进行代码解耦简直不要太爽。 但是我最近碰到了一个涉及到泛型的场景,常规套路下,在这个场景中使用该机制看起来会很傻,但…

CoSeg: Cognitively Inspired Unsupervised Generic Event Segmentation

名词解释 1.特征重建 特征重建是一种机器学习中常用的技术,通常用于自监督学习或无监督学习任务。在特征重建中,模型被要求将输入数据经过编码器(encoder)转换成某种表示,然后再经过解码器(decoder&#x…

中学数学研究杂志中学数学研究杂志社中学数学研究编辑部2024年第4期目录

教学纵横 高中数学选择性必修课程函数主线分析 柳双;吴立宝; 1-4 贯彻新课程理念 促学习能力提升——以“三角函数诱导公式”教学为例 陆雨轩; 4-6《中学数学研究》投稿:cn7kantougao163.com 对高中数学新课标教材新增知识点的价值分析 钱伟风;刘瑞美; …

商务分析方法与工具(十):Python的趣味快捷-公司财务数据最炫酷可视化

Tips:"分享是快乐的源泉💧,在我的博客里,不仅有知识的海洋🌊,还有满满的正能量加持💪,快来和我一起分享这份快乐吧😊! 喜欢我的博客的话,记得…

C# WinForm —— 18 NumericUpDown 介绍

1. 简介 数字显示框,通过向上、向下按钮来 增加/减小 显示的数值 2. 常用属性 属性解释(Name)控件ID,在代码里引用的时候会用到,一般以 numUD 开头Hexadecimal数值 up-down 控件的值是否应以十六进制显示Increment每单击一下按钮,增加或减…