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

news2024/11/28 4:34:47

一、设计模式介绍

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

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

下面是常见的 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 {
    @Override
    Product factoryMethod() {
        return new ConcreteProductA();
    }
}

class ConcreteCreatorB extends Creator {
    @Override
    Product 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 {
    @Override
    AbstractProductA createProductA() {
        return new ConcreteProductA1();
    }

    @Override
    AbstractProductB createProductB() {
        return new ConcreteProductB1();
    }
}

class ConcreteFactory2 extends AbstractFactory {
    @Override
    AbstractProductA createProductA() {
        return new ConcreteProductA2();
    }

    @Override
    AbstractProductB 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.coloradmin.cn/o/1670887.html

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

相关文章

关于修改ant-design-vue的table组件背景色遇到闪动的问题

项目中需要修改表格的背景色为以下样式 修改完之后发现表格行还有个hover的背景色,于是再次重置样式如下 .ant-table-tbody > tr {&:hover {td {// background: red !important;background: transparent !important;}}}这样重置之后,hover的样式…

【中级软件设计师】上午题16-算法(应试考试简略版)

上午题16-算法 1 回溯法1.1 n皇后问题 2 分治法3 动态规划3.1 0-1背包问题3.2 最长公共子序列3.3 矩阵连乘 4 贪心算法5 分支限界法总结 1 回溯法 深度优先方法搜索 1.1 n皇后问题 2 分治法 一般来说,分治算法在每一层递归上都有3个步骤 (1&#xff…

【C++】详解STL的适配器容器之一:优先级队列 priority_queue

目录 堆算法 概述 向下调整建堆 向上调整建堆 建堆算法 仿函数 概述 使用介绍 emtpy size top push pop 模拟实现 仿函数 框架 向下调整算法 向上调整算法 pop push empty top 要理解优先级队列,需要有如下知识 STL容器之一的vector&#xf…

嵌入式:基于STM32的RFID访问控制系统

在商业和住宅建筑中,访问控制系统是确保安全的关键组件。使用射频识别(RFID)技术,我们可以创建一个安全、方便的门禁系统。本教程将详细说明如何使用STM32微控制器实现RFID基础的门禁系统,该系统能够控制电子锁并记录访…

品鉴中的品鉴笔记:如何记录和分享自己的品鉴心得

品鉴云仓酒庄雷盛红酒的过程,不仅是品尝美酒,更是一次与葡萄酒深度对话的旅程。为了更好地记录和分享自己的品鉴心得,养成写品鉴笔记的习惯是十分必要的。 首先,选择一个适合的记录工具。可以是传统的笔记本,也可以是…

爆!1688「搜索推广」实操打法,8大要点快速上手!

想要1688平台上提高商品的搜索排名和曝光率,吸引更多的潜在客户并提升销量,店雷达将尽量具体地介绍相关操作方法和运营思路,建议大家收藏起来慢慢看。 一、了解1688平台搜索方式 1、品搜:这是买家最常用的搜索方式,通…

消息中间件是什么?有什么用?常见的消息中间件有哪些?

1.什么是消息中间件? 消息中间件基于队列模型在网络环境中为应用系统提供同步或异步、可靠的消息传输的支撑性软件系统。 2.现实中的痛点: 1.Http请求基于请求与响应的模型,在高并发的情况下,客户端发送大量的请求达到服务器端…

C# WinForm —— 19 PictureBox 介绍

1. 简介 PictureBox 主要用于显示图像,也可以给它注册单击事件,来把它变成一个按钮 2. 常用属性 属性解释(Name)控件ID,在代码里引用的时候会用到,一般以 pixB 开头BackColor控件的背景色BackgroundImage控件的背景图像BorderStylePictur…

开放式耳机什么品牌最好?2024五款新晋爆款产品推荐!

​如今的耳机市场天下三分,有线入耳式耳机、蓝牙无线入耳式耳机以及开放式耳机,传统的有线入耳式耳机戴着不稳就算了,线很容易揉成一团,看着就头大;无线入耳式的耳机,同样面临着戴着不稳的问题,…

如何在群晖NAS中开启FTP并实现使用公网地址远程访问传输文件

文章目录 1. 群晖安装Cpolar2. 创建FTP公网地址3. 开启群晖FTP服务4. 群晖FTP远程连接5. 固定FTP公网地址6. 固定FTP地址连接 本文主要介绍如何在群晖NAS中开启FTP服务并结合cpolar内网穿透工具,实现使用固定公网地址远程访问群晖FTP服务实现文件上传下载。 Cpolar内…

Nginx内网环境开启https

文章目录 前言一、open-ssl1. 验证2. 安装3.生成ssl证书 一、nginx1. 验证支持模块2. 安装必要模块2.1 重新编译nginx2.2 替换原文件 3. 配置https 总结 前言 nginx开启https前提: 服务器支持open-sslnginx 包含--with-http_ssl_module --with-stream --with-stre…

JavaScript原理篇——Promise原理及笔试题实战演练

Promise 是 JavaScript 中用于处理异步操作的对象,它代表了一个可能还没有完成的操作的最终完成或失败,以及其结果值。Promise 对象有三种状态: Pending(进行中):初始状态,既不是成功&#xff0…

前端js面试题--从字符串中删除删除注释代码

问题:从字符串中删除删除注释代码 描述: solution(weex,rex # and react\nflutter\nnative ssss !hybrid app, [#, !]) 写一个solution函数清除后面参数数组里面的字符串 打印效果 代码1 思路: 将字符全凡是有去掉标志符号的全部添加\n…

flutter 使用Scrollbar 时出现 滚动条不置顶问题

Flutter 使用 CupertinoScrollbar 、Scrollbar 与 ListView.builder 结合使用时, 当把 ListView.builder 边距设置为 padding: const EdgeInsets.all(0) 的时候, Scrollbar 的滚动条不置顶。 如图:右侧边上的滚动条 解决方法: …

什么是.faust勒索病毒?应该如何防御?

faust勒索病毒详细介绍 faust勒索病毒是一种新型的勒索软件,最早出现在2018年。该病毒通过加密计算机系统中的文件并要求支付赎金来解锁文件,从而获取经济利益。与传统的勒索软件相比,faust勒索病毒采用了更加先进的加密算法和隐藏技术&#…

浅析视频汇聚EasyCVR视频融合云平台在机场安防智能检测建设中的应用

一、背景 机场作为国家交通枢纽和对外开放的窗口,其安全运行直接关系到乘客的生命安全、国家形象以及社会经济稳定。随着全球航空业的快速发展和人们出行需求的持续增长,机场作为重要的交通枢纽,其客流量和货运量均呈现出快速增长的态势。然而…

【鸿蒙+全国产瑞芯微】智慧楼宇解决方案 | 如何实现多场景下智慧化、精细化楼宇管理?

随着数字化、智能化与工作生活的联结日渐紧密,聚焦人性化服务,以数字和科技匹配多重需求,加速商业楼宇智能化转型的脚步,逐步形成智慧楼宇产品矩阵。 方案亮点 01/数字标牌——形象展示 企业文化宣传、公告通知等 播放内容统一远…

实时追踪维修进度,报修管理小程序让你省心又省力!

随着生活、工作节奏的日益加快,日常的售后报修、故障报修处理流程给我们带来种种困扰。我们都知道大多数企业、个人用户还在使用传统报修方式,如电话报修、纸质报修单等方式,不仅效率低下,而且难以追踪维修进度,给我们…

C# 使用Queue高效检索树行数据符合条件的数据,并返回完整树形数据示例

最近有项目需要加载大型树数据,数据大概3W条 后端使用C# NET6 前端使用Vue3 elementuiplus 虚拟tree 》解决大型树数据加载 遇到的问题是后端在检索数据时,要返回匹配数据的完整树目录 1.因为单条数据没有存放完整路径,需要通过父级ID逐…

第六节笔记及作业----Lagent AgentLego 智能体应用搭建

关于 Agent 的相关理论 大语言模型存在一些局限性,比如会出现幻觉问题、有时效性问题以及可靠性问题。智能体的定义是具备感知、决策和行动能力的实体。智能体主要由感知部分、大脑部分和动作部分组成。智能体有多种类型,如 ReAct 类型(侧重…