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

简介: 深入浅出设计模式 - 工厂模式

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

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

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

1687837432709.jpg

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

1686494501743.jpg

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

目录
相关文章
|
开发工具
【云手机】(systemctl)解决:System has not been booted with systemd as init system (PID 1). Can't ope...
【云手机】(systemctl)解决:System has not been booted with systemd as init system (PID 1). Can't ope...
3285 0
win10桌面窗口管理器进程内存占用大解决方法
win10桌面窗口管理器进程内存占用大解决方法
791 0
|
网络协议 Java 编译器
Java常见异常及对应解决办法
Java常见异常及对应解决办法
189 10
|
机器学习/深度学习 算法
GBDT算法超参数评估(一)
GBDT(Gradient Boosting Decision Tree)是一种强大的机器学习技术,用于分类和回归任务。超参数调整对于发挥GBDT性能至关重要。其中,`n_estimators`是一个关键参数,它决定了模型中弱学习器(通常是决策树)的数量。增加`n_estimators`可以提高模型的复杂度,提升预测精度,但也可能导致过拟合,并增加训练时间和资源需求。
|
监控 应用服务中间件 开发者
EDAS 通知报警|学习笔记
快速学习 EDAS 通知报警EDAS通知报警功能在应用管理功能中,主要包含三个功能,即报警规则的设定、报警联系人的维护以及报警记录。
255 0
|
前端开发 容器
第十八章 React中的样式模块化处理
第十八章 React中的样式模块化处理
137 2
|
数据可视化 Go
ggplot2 |legend参数设置,图形精雕细琢
ggplot2 |legend参数设置,图形精雕细琢
438 0
|
设计模式 缓存 Java
Spring监听器用法与原理详解(带ApplicationListener模型图)(2)
Spring监听器用法与原理详解(带ApplicationListener模型图)
366 0
|
机器学习/深度学习 存储 Cloud Native
【推荐】最适合新手的5个深度学习实战项目
【推荐】最适合新手的5个深度学习实战项目
|
物联网 TensorFlow 算法框架/工具
联邦学习 (FL) 中常见的3种模型聚合方法的 Tensorflow 示例
联合学习 (FL) 是一种出色的 ML 方法,它使多个设备(例如物联网 (IoT) 设备)或计算机能够在模型训练完成时进行协作,而无需共享它们的数据。
517 0
联邦学习 (FL) 中常见的3种模型聚合方法的 Tensorflow 示例