深入浅出设计模式 - 工厂模式

news2024/12/26 12:06:29

博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌

Java知识图谱点击链接:体系化学习Java(Java面试专题)

💕💕 感兴趣的同学可以收藏关注下不然下次找不到哟💕💕

在这里插入图片描述

文章目录

  • 1、什么是工厂模式
  • 2、简单工厂模式
    • 2.1、简单工厂模式介绍
    • 2.2、简单工厂模式有什么优缺点
    • 2.3、简单工厂模式结构
    • 2.4、简单工厂模式代码案例
  • 3、工厂方法模式
    • 3.1、工厂方法模式介绍
    • 3.2、工厂方法模式有什么优缺点
    • 3.3、工厂方法模式结构
    • 3.3、工厂方法模式代码案例

1、什么是工厂模式

工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在工厂模式中,我们可以创建一个工厂类,该类负责创建其他类的对象。这样,我们就可以将对象的创建过程与客户端代码分离开来,从而提高了代码的可维护性和灵活性。

工厂模式有三种常见的实现方式:简单工厂模式、工厂方法模式和抽象工厂模式。简单工厂模式通过一个工厂类来创建所有的产品对象,工厂方法模式通过一个抽象工厂接口和多个具体工厂类来创建不同类型的产品对象,抽象工厂模式则通过一个抽象工厂接口和多个具体工厂类来创建一系列相关或相互依赖的产品对象。

2、简单工厂模式

在这里插入图片描述

2.1、简单工厂模式介绍

简单工厂模式是一种创建型设计模式,它提供了一种创建对象的最佳方式。在简单工厂模式中,我们可以创建一个工厂类,该类负责根据客户端的请求创建不同类型的产品对象。这样,我们就可以将对象的创建过程与客户端代码分离开来,从而提高了代码的可维护性和灵活性。

简单工厂模式包含三个主要角色:工厂类、抽象产品类和具体产品类。其中,工厂类负责创建产品对象,抽象产品类定义了产品对象的公共接口,具体产品类则实现了抽象产品类的接口,表示真正的产品对象。

在简单工厂模式中,客户端不需要知道具体产品的类名,只需要知道对应的参数即可。工厂类根据客户端传入的参数来决定创建哪种类型的产品对象,并返回该对象给客户端使用。这样,客户端就可以通过工厂类创建所需要的对象,而不需要关心对象的创建过程。

需要注意的是,简单工厂模式虽然简单易用,但是它也有一些缺点。例如,工厂类集中了所有产品的创建逻辑,如果产品类型过多或者产品的创建逻辑复杂,工厂类的代码会变得非常臃肿。此外,一旦工厂类出现问题,将会导致整个系统的崩溃。因此,在使用简单工厂模式时需要注意这些问题。

2.2、简单工厂模式有什么优缺点

简单工厂模式的优点:

  1. 隐藏了对象创建的复杂度,客户端只需要知道所需对象的类型即可,无需了解对象创建的细节。

  2. 降低了客户端和具体产品类之间的耦合度,客户端只需要依赖抽象产品类和工厂类即可,不需要依赖具体产品类。

  3. 可以通过工厂类来集中控制产品对象的创建过程,从而提高了代码的可维护性和灵活性。

简单工厂模式的缺点:

  1. 工厂类集中了所有产品的创建逻辑,如果产品类型过多或者产品的创建逻辑复杂,工厂类的代码会变得非常臃肿。
  2. 一旦工厂类出现问题,将会导致整个系统的崩溃。
  3. 对于新增产品的支持不够灵活,如果需要新增产品,必须修改工厂类的代码,违反了开闭原则。
  4. 简单工厂模式的扩展性不够好,一旦需要支持新的产品类型,就需要修改工厂类的代码,不符合开闭原则的要求。​

2.3、简单工厂模式结构

简单工厂模式包含如下几个角色:

  1. 抽象产品类(Product):定义了产品的公共接口,所有具体产品类都必须实现这些公共接口。

  2. 具体产品类(ConcreteProduct):是抽象产品类的子类,实现了抽象产品类定义的公共接口,具体产品类是简单工厂模式中创建的对象。

  3. 工厂类(Factory):负责创建具体产品类的实例,是简单工厂模式的核心,包含了创建产品对象的逻辑。

在简单工厂模式中,客户端通过工厂类来创建具体产品类的实例,而不是直接通过 new 关键字来创建对象。客户端只需要提供所需产品的类型,工厂类就会根据所提供的类型来创建相应的产品对象。这样,客户端就可以通过工厂类来获取所需的产品对象,而无需了解产品对象的创建细节。

2.4、简单工厂模式代码案例

我们用一段代码介绍下简单工厂模式结构:

首先,定义一个抽象产品类 Product ,它包含一个抽象方法 use() ,表示产品的使用方法:

package com.pany.camp.design.principle.simple;

/**
 *
 * @description:  抽象产品类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 10:56
 */
public abstract class Product {

    public abstract void use();
}

然后,定义具体产品类 ProductA 和 ProductB ,它们继承自抽象产品类 Product ,并实现了抽象方法 use() :

package com.pany.camp.design.principle.simple;

/**
 *
 * @description:   产品 A
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 10:57
 */
public class ProductA extends Product {

    @Override
    public void use() {
        System.out.println("使用产品A");
    }
}

package com.pany.camp.design.principle.simple;

/**
 *
 * @description:  产品 B
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 10:57
 */
public class ProductB extends Product {
    
    @Override
    public void use() {
        System.out.println("使用产品B");
    }
}

接下来,定义简单工厂类 SimpleFactory ,它包含一个静态方法 createProduct(String type) ,根据传入的参数 type 创建具体产品对象并返回:

package com.pany.camp.design.principle.simple;

/**
 *
 * @description:  简单工厂类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 10:58
 */
public class SimpleFactory {

    public static Product createProduct(String type) {
        if ("A".equals(type)) {
            return new ProductA();
        } else if ("B".equals(type)) {
            return new ProductB();
        } else {
            throw new IllegalArgumentException("Unsupported product type: " + type);
        }
    }
}

最后,在客户端代码中,通过简单工厂类 SimpleFactory 创建具体产品对象,并调用其方法:

package com.pany.camp.design.principle.simple;

/**
 *
 * @description:  客户端类
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 10:59
 */
public class Client {

    public static void main(String[] args) {
        Product productA = SimpleFactory.createProduct("A");
        productA.use(); // 输出:使用产品A
        Product productB = SimpleFactory.createProduct("B");
        productB.use(); // 输出:使用产品B
    }
}

输出结果:

使用产品A
使用产品B

Process finished with exit code 0

3、工厂方法模式

3.1、工厂方法模式介绍

工厂方法模式是一种常用的创建型设计模式,它将对象的创建过程延迟到子类中进行。工厂方法模式定义了一个抽象工厂类,其中包含一个抽象的工厂方法,用于创建产品对象。具体的产品对象由具体的工厂子类来创建。这样,客户端代码只需要与抽象工厂类和抽象产品类交互,无需直接与具体工厂类和具体产品类交互,从而实现了客户端代码与具体实现的解耦。

工厂方法模式的核心思想是“定义一个创建对象的接口,但让子类决定哪个类实例化”。这样,工厂方法模式可以让类的实例化延迟到子类中进行,从而实现了解耦和复用。

工厂方法模式的主要角色包括抽象工厂类、具体工厂类、抽象产品类和具体产品类。其中,抽象工厂类定义了一个抽象的工厂方法,用于创建产品对象;具体工厂类实现了抽象工厂类中的工厂方法,用于创建具体的产品对象;抽象产品类定义了产品的抽象方法,具体产品类实现了抽象产品类中的抽象方法,用于提供具体的产品功能。

3.2、工厂方法模式有什么优缺点

工厂方法模式的优点包括:

  1. 通过工厂方法模式,客户端代码无需关心具体产品类的实现细节,只需关心抽象产品类和抽象工厂类的接口定义,从而实现了客户端代码与具体实现的解耦。

  2. 工厂方法模式可以实现对象的复用,由于客户端只与抽象工厂类和抽象产品类交互,因此可以在不修改客户端代码的情况下,通过增加具体工厂类和具体产品类来扩展系统功能。

  3. 工厂方法模式可以实现更好的扩展性,由于具体工厂类和具体产品类的创建过程在子类中实现,因此可以通过增加子类来扩展系统功能,而无需修改抽象工厂类和抽象产品类的接口定义。

工厂方法模式的缺点包括:

  1. 工厂方法模式需要定义抽象工厂类和抽象产品类,这增加了系统的抽象性和理解难度。

  2. 工厂方法模式增加了系统的代码量,由于需要定义抽象工厂类和抽象产品类,因此需要编写更多的代码。

  3. 工厂方法模式在增加新产品时,需要编写新的具体产品类和具体工厂类,这增加了系统的维护成本。

3.3、工厂方法模式结构

工厂方法模式的结构包括四个主要的角色:抽象工厂类、具体工厂类、抽象产品类和具体产品类。它们之间的关系如下:

  1. 抽象工厂类(Creator):定义了一个抽象的工厂方法,用于创建产品对象。它是工厂方法模式的核心,所有具体工厂类都必须实现这个接口。

  2. 具体工厂类(Concrete Creator):实现了抽象工厂类中的工厂方法,用于创建具体的产品对象。

  3. 抽象产品类(Product):定义了产品的抽象方法,具体产品类实现了抽象产品类中的抽象方法,用于提供具体的产品功能。

  4. 具体产品类(Concrete Product):实现了抽象产品类中的抽象方法,用于提供具体的产品功能。

工厂方法模式的结构图如下:

|  具体工厂类A   |
                +-----------------+
                |  工厂方法()    |
                +-----------------+
                          /\
                          |
                          |
                +-----------------+
                |  抽象产品类    |
                +-----------------+
                |  抽象方法()    |
                +-----------------+
                          /\
                          |
                          |
                +-----------------+
                |  具体产品类A   |
                +-----------------+
                |  抽象方法()    |
                +-----------------+

在工厂方法模式中,客户端只需要与抽象工厂类和抽象产品类交互,具体工厂类和具体产品类的创建过程被延迟到子类中进行。这样,客户端代码与具体实现解耦,可以更加灵活地扩展系统功能。

3.3、工厂方法模式代码案例

抽象产品类:

package com.pany.camp.design.principle.factory;

/**
 *
 * @description:  抽象产品类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:14
 */
public abstract class Operation {
    
    public abstract double getResult(double a, double b);
}

具体的产品:

/**
 *
 * @description:  加法
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:14
 */
public class AddOperation extends Operation {
    @Override
    public double getResult(double a, double b) {
        return a + b;
    }
}
package com.pany.camp.design.principle.factory;

/**
 *
 * @description:  减法
 * @copyright: @Copyright (c) 2022
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0
 * @createTime: 2023-06-27 11:16
 */
public class SubOperation extends Operation {
    @Override
    public double getResult(double a, double b) {
        return a - b;
    }
}

抽象工厂类:

package com.pany.camp.design.principle.factory;

/**
 *
 * @description:  抽象工厂类
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:12
 */
public abstract class OperationFactory {
    
    public abstract Operation createOperation();
}

具体的工厂

package com.pany.camp.design.principle.factory;

/**
 *
 * @description:  加法运算工厂
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:16
 */
public class AddFactory extends OperationFactory {

    @Override
    public Operation createOperation() {
        return new AddOperation();
    }
}
package com.pany.camp.design.principle.factory;

/**
 *
 * @description:  减法运算工厂
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:17
 */
public class SubFactory extends OperationFactory {
    
    @Override
    public Operation createOperation() {
        return new SubOperation();
    }
}

客户端

package com.pany.camp.design.principle.factory;

/**
 *
 * @description: 客户端
 * @copyright: @Copyright (c) 2022 
 * @company: Aiocloud
 * @author: pany
 * @version: 1.0.0 
 * @createTime: 2023-06-27 11:18
 */
public class Client {
    
    public static void main(String[] args) {
        OperationFactory factory = new AddFactory(); // 创建加法运算工厂对象
        Operation operation = factory.createOperation(); // 创建加法运算对象
        double result = operation.getResult(1, 2); // 进行加法运算
        System.out.println(result); // 输出 3.0

        factory = new SubFactory(); // 创建减法运算工厂对象
        operation = factory.createOperation(); // 创建减法运算对象
        result = operation.getResult(2, 1); // 进行减法运算
        System.out.println(result); // 输出 1.0
    }
}

输出结果如下:

Connected to the target VM, address: '127.0.0.1:50223', transport: 'socket'
3.0
1.0
Disconnected from the target VM, address: '127.0.0.1:50223', transport: 'socket'

Process finished with exit code 0

在这里插入图片描述

💕💕 本文由激流原创,首发于CSDN博客,博客主页 https://blog.csdn.net/qq_37967783?spm=1010.2135.3001.5421
💕💕喜欢的话记得点赞收藏啊

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

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

相关文章

目标检测舰船数据集整合

一、光学数据集 1、 DIOR 数据集(已下载yolo版本)(论文中提到过) “DIOR”是一个用于光学遥感图像目标检测的大规模基准数据集。数据集包含23463个图像和192472个实例,涵盖20个对象类。这20个对象类是飞机、机场、棒球场、篮球场、桥梁、烟囱…

CSS 边框盒子

文章目录 边框盒子 边框盒子 提示:这里可以添加本文要记录的大概内容: 默认的盒子类型是内容盒子:content-box 在内容盒子中,width和height是内容尺寸 盒子整体的尺寸内容的尺寸两个边框两个内边距 css3引入了新的盒子类型&…

Linux——对动静态库的优缺点和底层剖析对比

目录 静态库底层剖析: 所以静态库的优缺点总结: 动态库底层剖析: 所以使用动态库的优缺点剖析: 静态库底层剖析: 如上图:file1.exe被加载到了内存,成为了进程,因为代码中都有pri…

【Docker】docker安装配置Jenkins

docker 安装 Jenkins #拉镜像 docker pull jenkins/jenkins#创建卷(volume) docker volume create jenkins_home#制作容器并启动 docker run -d \ -p 8080:8080 \ -p 50000:50000 \ -v jenkins_home:/var/jenkins_home \ -v /usr/lib/jvm/java-8-openjdk-amd64:/usr/local/java…

IMX6ULL系统移植篇-镜像烧写方法

一. 烧录镜像简介 本文我们就来学习:windows 系统下烧录镜像的方法。 如何使用 NXP 官方提供的 MfgTool 工具通过 USB OTG 口来 烧写系统。 二. windows下烧录镜像 1. 烧录镜像前准备工作 (1)从开发板上拔下 SD卡。 (2…

SpringBoot中如何优雅的统一全局返回格式与处理系统异常?

在领域驱动设计(DDD)中,接口层主要负责处理与外部系统的交互,包括接收用户或外部系统的请求,调用应用层服务处理请求,以及将处理结果返回给请求方。 我发现一些代码中,接口的返回值类型众多&am…

chatgpt赋能python:Python语言单词大全:从入门到精通

Python语言单词大全:从入门到精通 Python是一种高级编程语言,适用于各种应用领域,如数据科学、机器学习、网站开发和自动化脚本编写等。Python语言有其内置的语法和功能,我们将在本文中逐一介绍和解释。 1. Python中最基本的单词…

K8S集群安全之安全机制

1. 安全机制说明: Kubernetes作为一个分布式集群的管理工具,保证集群的安全性是其一个重要的任务。API Server是集群内部各个组件通信的中介,也是外部控制的入口。所以Kubernetes的安全机制基本就是围绕保护APIServer来设计的。Kubernetes使…

小程序实现双列布局

目录 1 双列布局2 采用流式布局3 采用网格布局总结 小程序中双列布局是一个常见的效果,比如在电商小程序的商品推荐,效果如下: 1 双列布局 双列布局的话特点是随着数据的增多,我们会出现偶数或者奇数的问题,如果是偶…

【Data Studio 2.1.0连接openGauss2.1.0】

Data Studio 2.1.0连接openGauss2.1.0 一、实验环境说明二、配置客户端接入方式三、Data Studio2.1.0连接openGauss数据库 一、实验环境说明 openGauss2.1.0版本Data Studio 2.1.0 版本 二、配置客户端接入方式 【以下操作是omm用户进行】 修改配置文件pg_hba.conf&#xf…

12--Gradle进阶 - Gradle任务的类型

12--Gradle进阶 - Gradle任务的类型 任务类型 前面我们定义的task 都是DefaultTask 类型的,如果要完成某些具体的操作完全需要我们自己去编写gradle 脚本,势必有些麻烦,那有没有一些现成的任务类型可以使用呢?有的,Gradle 官网给出…

C. Tenzing and Balls - dp

分析: 补题。当时不明白的点是如何快速查询相同元素的下标,可以用last[a[i]]表示与a[i]相同的最近的一个数的下标,可以遍历数组的同时实现下标的查询和变化,不断通过遍历来更新last[a[i]]的值,即last[a[i]]i。 然后是状…

衡石bi的几种跳转方式

衡石bi的几种跳转方式 通过点击表格的单元格跳转(带参) 点击首页的表格里任意一行的单元格跳转到明细页的企业相关数据 这两个数据集都是有一个info_uuid的主键,我们知道每个控件都可以设置交互的方式进行跳转应用内的仪表盘。 点击首页里要设置跳转的控件右上角的…

maven基础教程

一、安装moven 1、下载maven包 首先到maven官网下载安装包,解压到本地目录,然后配置环境变量。 maven下载地址:https://maven.apache.org/download.cgi 2、配置环境变量 然后打开环境变量,添加 MAVEN_HOME 系统变量&#xff…

JVM-jvisualvm性能监控可视化工具使用与eden-s0-s1分配分析

目录 第一步:安装jvisualvm 第二步:安装VisualvmGc插件 方式一:jvisualvm工具直接下载安装 方式二:去官网下载导入安装 总结 第三步:idea安装VisualvM Launcher插件 第四步:演示young中eden、s0、s1垃…

轻量级数据交换格式:jsoncpp

"这不属于我&#xff0c;因为沉默背后&#xff0c;也有冲动" 一、认识json (1) 为什么有那么多的数据交换格式&#xff1f; 比如说&#xff0c;现在我有下面的数据: #include <iostream> #include <string>int main() {std::string name "张三&q…

比较两个突出的node.js框架:koa和express

目录 一、Koa 和 Express 的介绍 二、Koa 和 Express 的区别 1.异步编程方式不同 2.错误处理方式不同 三、Koa 和 Express 的优缺点 1.Express 的优点 2.Express 的缺点 3.Koa 的优点 4.Koa 的缺点 总结 接上文讲述了 koa框架&#xff0c;这边文章比较一下这两个突出…

CentOS系统忘记密码了改怎么修改重置103.88.34.X

首先&#xff0c;打开centos7&#xff0c; 在正常系统入口按↑和↓"e"&#xff0c;会进入edit模式 然后找到以“Linux16”开头的行&#xff0c;在该行的最后面输入“init/bin/sh” 按下ctrlx组合键来启动系统 接下来再输入“mount -o remount,rw /”(注意mount与…

ceph对象存储使用总结

ceph对象存储使用总结 大纲 基础概念安装对象存储网关RADOS网关配置对象存储网关RADOS网关修改RADOS网关端口修改支持https访问RADOS网关使用s3cmd操作对象存储Ceph dashboard管理RADOS网关使用java程序操作对象存储 基础准备 操作系统 ubuntu~18.04ceph版本 Octopus v15.2…

适用于 3DS Max 和 Cinema 4D 的 Chaos Corona 10重磅推出!

Chaos 发布了 Corona 10&#xff0c;适用于3DS Max和Cinema 4D 的渲染器的最新版本 &#xff01;Corona 10 对软件的多项现有功能进行了更新&#xff0c;包括贴花、体积渲染、景深和程序云。 目前渲云云渲染已支持Corona 10&#xff0c;支持批量渲染&#xff0c;批量出结果&am…