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

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

博主介绍: ✌博主从事应用安全和大数据领域,有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
💕💕喜欢的话记得点赞收藏啊

目录
相关文章
|
7月前
|
设计模式 算法 架构师
【搞懂设计模式】设计模式与面向对象原则
【搞懂设计模式】设计模式与面向对象原则
68 1
|
7月前
|
设计模式 算法 Java
设计模式实战
**设计模式的应用与案例** 设计模式是解决常见软件设计问题的最佳实践,有助于提升代码质量和可维护性。有效利用设计模式的步骤包括:理解业务需求、识别问题、选择合适模式、学习研究和适时调整。在实际工作中,例如,通过结合工厂模式和策略模式,解决了多端页面配置筛选逻辑,避免接口爆炸;使用模板方法模式,将复杂业务逻辑拆分为可复用步骤,提高了代码扩展性。设计模式虽好,但应适度,避免过度复杂化。
51 1
|
设计模式 Java
重学设计模式-工厂模式
  今天来说一下工厂模式(简单工厂,工厂方法,抽象工厂),工厂模式(Factory Pattern)是 Java 中最常用的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,在工厂模式中,我们在创建对象时不会对客户端暴露创建逻辑,并且是通过使用一个共同的接口来指向新创建的对象。
69 0
|
7月前
|
设计模式 前端开发 C++
什么是设计模式?
什么是设计模式?
70 0
|
设计模式 算法 安全
深入浅出设计模式 - 策略模式
深入浅出设计模式 - 策略模式
127 0
深入浅出设计模式 - 策略模式
|
设计模式 SQL Java
为什么一定要学习设计模式
先来看一个生活案例,当我们开心时,也许会寻求享乐。在学习设计模式之前,你可能会这样感叹:
55 0
|
设计模式 XML 安全
深入浅出设计模式 - 建造者模式
深入浅出设计模式 - 建造者模式
95 0
深入浅出设计模式 - 建造者模式
|
设计模式 安全 Java
深入浅出设计模式 - 装饰者模式
深入浅出设计模式 - 装饰者模式
115 0
深入浅出设计模式 - 装饰者模式
|
设计模式 缓存 安全
深入浅出设计模式 - 享元模式
深入浅出设计模式 - 享元模式
120 0
深入浅出设计模式 - 享元模式
|
设计模式 容器
2022-9-19-C++各种设计模式的简单总结
2022-9-19-C++各种设计模式的简单总结
79 0