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

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

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

目录
相关文章
|
4月前
|
设计模式 开发框架 前端开发
设计模式一
设计模式是面向对象编程的实践经验,旨在解决一系列问题,促进软件的可升级和维护。它分为创建型(如工厂、单例模式)、结构型(适配器、装饰器模式等)和行为型(观察者、策略模式等)三大类。J2EE模式关注表示层,包括MVC模式等。设计模式的七大原则包括里氏替换、依赖倒置、开闭原则、单一职责、接口隔离、迪米特原则和合成复用原则,这些原则有助于减少耦合和提高代码可读性。接口作为契约和层间对接工具,约束类型行为并允许实现多继承。
|
5月前
|
设计模式 存储 安全
[设计模式] 常见的设计模式
[设计模式] 常见的设计模式
|
12月前
|
设计模式 安全 Java
设计模式~单列模式-01
单列模式 1、饿汉式 2、懒汉式(lazy loading) 3、双重检测 4、静态内部类
30 0
|
设计模式 存储 算法
|
设计模式 算法 程序员
【3W2H设计模式】什么是设计模式
【3W2H设计模式】什么是设计模式
254 0
|
设计模式 容器
2022-9-19-C++各种设计模式的简单总结
2022-9-19-C++各种设计模式的简单总结
72 0
|
设计模式 算法 C#
使用c#实现23种常见的设计模式
使用c#实现23种常见的设计模式
77 0
|
设计模式 算法 数据库连接
|
设计模式 消息中间件 Java
一起来学设计模式之认识设计模式
前言 目前正在出一个设计模式专题系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~ 本节给大家讲一下设计模式基本概念,它的基本原则以及有哪些设计模式~ 本专题的所有案例代码主要以Java语言为主, 好了, 废话不多说直接开整吧~ 设计模式初识 设计模式是一种经过验证的、被广泛应用的解决特定问题的软件设计方案,它提供了一种在软件设计中反复使用的解决方案。设计模式通常描述了一个问题的情境、解决方案和解决方案的优点和缺点。设计模式不是一种具体的编程语言特性或库,而是一种通用的设计思想和方法。
|
设计模式 存储 算法
【设计模式】常用的10种设计模式
收录一些自己在开发过程中比较常用的模式,整理出来以便自己梳理和复习,从而熟能生巧,举一反三。下面只列出模式的脉络大纲,取最核心的逻辑进行讲解。
105 0
【设计模式】常用的10种设计模式