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

一、设计模式介绍

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

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

下面是常见的 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.hqwc.cn/news/695858.html

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

相关文章

嗨动PDF编辑器适合你的pdf编辑器,试试吧!

pdf编辑器有哪些?在数字化办公日益普及的今天,PDF文档因其跨平台、高保真度的特性而备受欢迎。无论是工作汇报、学术研究还是日常学习,我们都需要对PDF文档进行编辑、修改和整理。然而,如何选择合适的PDF编辑器却成了许多人头疼的…

【目标检测论文解读复现NO.38】基于改进YOLOv8模型的轻量化板栗果实识别方法

前言 此前出了目标改进算法专栏,但是对于应用于什么场景,需要什么改进方法对应与自己的应用场景有效果,并且多少改进点能发什么水平的文章,为解决大家的困惑,此系列文章旨在给大家解读最新目标检测算法论文&#xff0c…

C++ | Leetcode C++题解之第78题子集

题目&#xff1a; 题解&#xff1a; class Solution { public:vector<int> t;vector<vector<int>> ans;void dfs(int cur, vector<int>& nums) {if (cur nums.size()) {ans.push_back(t);return;}t.push_back(nums[cur]);dfs(cur 1, nums);t.po…

CRMEB开源打通版/标准版v4电商商城系统小程序发布之后无法生成海报问题

小程序产品分销二维码生成不了 开发者工具可以生成海报&#xff0c;但是发布之后无法生成 1.在开发者工具中&#xff0c;将不校验合法域名关闭 2.点击生成海报&#xff0c;查看console3.将域名填写到微信公众平台小程序的download合法域名中 网址微信公众平台

04、 .java程序用 editplus 工具打开的过程及在 editplus 工具中配置 java/javac 命令的过程

EditPlus 工具的使用&#xff1a; 1、安装 editplus 工具的过程&#xff1a;其一、安装包地址&#xff1a;其二、安装步骤&#xff1a; 2、使用 editplus 工具打开 .java 程序的过程&#xff1a;其一、修改默认打开 .java 的工具&#xff1a;其二、效果展示&#xff1a; 3、在 …

RSAC2024: 洞悉安全新趋势 - 天空卫士前沿观察

以"可能的艺术"&#xff08;The Art of the Possible&#xff09;为主题&#xff0c;备受瞩目的RSA Conference 2024&#xff08;RSAC2024&#xff09;已于5月6日在旧金山盛大开幕。这一年度盛会不仅是网络安全领域最新技术与趋势的展示窗口&#xff0c;更是全球网络…

24软考信管冲刺资料 |想上岸得对自己狠一点,建议统统背下来!!!

距离软考考试的时间越来越近了&#xff0c;趁着这两周赶紧准备起来。 今天给大家整理了——信息系统管理工程师冲刺资料 &#xff0c;都是核心重点&#xff0c;有PDF&#xff0c;打印出来直接背。 一、考试科目&#xff1a; 科目一&#xff1a;综合知识 【总分&#xff1a;75分…

移动端自动化测试工具 Appium 之自定义报告

文章目录 一、背景二、具体实现1、保存结果实体2、工具类3、自定义报告监听类代码4、模板代码4.1、report.vm4.2、执行xml 三、总结 一、背景 自动化测试用例跑完后报告展示是体现咱们价值的一个地方咱们先看原始报告。 上面报告虽然麻雀虽小但五脏俱全&#xff0c;但是如果用…

论文查重率好高啊,怎论文降重怎么降?aigc降低怎么改?

论文降重成功了&#xff0c;知网查重8%&#xff0c;aigc检测0%&#xff01;本人之前分享过一些关于论文方面的内容&#xff0c;然后就有好多同学在后台问毕业论文降重和aigc减低的方法&#xff0c;由于本人时间问题&#xff0c;实在不能第一时间给大家一一回复&#xff0c;请大…

【C语言】指针(一)

目录 一、内存 1.1 ❥ 理解内存和地址的关系 1.2 ❥ 编址 二、指针变量 2.1 ❥ 取地址操作符&#xff08;&&#xff09; 2.2 ❥ 指针变量和解引用操作符&#xff08;*&#xff09; 2.3 ❥ 指针变量的大小 三、指针类型的意义 3.1 ❥ 指针的解引用 3.2 ❥ 指针-整数 3…

如何将 DFMini player MP3 模块与 Arduino 结合使用

要创建此项目&#xff0c;您将使用&#xff1a; DFPlayer迷你MP3模块 10kΩ电阻 开关按钮 面包板 Arduino UNO 杜邦线 现在&#xff0c;我们将学习如何构建该项目。 什么是DF Mini Player MP3模块 DFMini Player 模块是一个小型音乐播放器。它成本低、功耗低&#xff0c;可…

JSP ssm 房屋中介管理myeclipse开发mysql数据库springMVC模式java编程计算机网页设计

一、源码特点 JSP ssm 房屋中介管理系统是一套完善的web设计系统&#xff08;系统采用SSM框架进行设计开发&#xff0c;springspringMVCmybatis&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采…