设计模式之工厂模式的使用

发布于:2025-08-04 ⋅ 阅读:(10) ⋅ 点赞:(0)

1.工厂模式简介

当我们谈到工厂模式,其实是分为三种类型,其中包括简单工厂模式、工厂方法模式和抽象工厂模式,他们都属于创新型设计模式,主要的目的都是封装对象的创建过程,将对象的创建和使用分离开来,从而提高代码的可维护性和可扩展性。

1.1 简单工厂模式

简单工厂模式时最简单的工厂模式,它将对象的创建过程封装在一个工厂类中,使用的时候通过工厂类来创建对象。简单工厂模式通常只有一个工厂类和多个产品类,在使用时不需要关心具体的产品类,只需要知道它们的名称或者类型即可。

1.2 工厂方法模式

工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。当使用的时候通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换,符合开闭原则。

1.3 抽象工厂模式

抽象工厂模式时工厂方法模式的升级版,它定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建义类产品族对象,具体产品类实现产品组接口并负责创建义类产品对象。当使用的时候通过工厂接口和产品族接口来创建对象,具体的产品族和工厂类都可以在运行时动态切换,符合开闭原则

2.简单工厂模式实现

这里给出的操作抽象类Operation只是为了提高代码的可复用性,以及代码的可扩展性,加减乘除类只需要继承Operation类并根据相应的运算实现getResult 方法即可。

创建出简单工厂模式的工厂类,通过该工厂类去创建不同运算结果的产品类,比如加法产品,减法产品等等

在使用时无需关心产品类,正如上面代码上写的,我们根本没有出现任何产品类比如OperationAdd, OperationSub等等,而是将产品的创建全权交给工厂类来实现,我们需要做的时提供名字或者类型给工厂就可以拿到想要的产品。

上面的代码看起来代码的运行结果,运行逻辑都没问题,似乎天衣无缝,但是如果我们的计算器想要添加一个求m的n次幂的操作呢?

仔细回想一下,开闭原则:对修改关闭,对扩展开放。我在这里添加一个求m的n次幂不正是一个扩展吗?为什么会违反了开闭原则呢?

如果我们想要添加一个OperationPow的求幂操作,就是构建出一个OperationPow类来继承Operation抽象类并根据自己的求幂逻辑来重写getResult 方法即可,到这里一切都没有问题,都是属于扩展操作并不涉及任何修改的操作,

但是对应的OperationFactory工厂类中,却需要修改switch的逻辑,实打实的修改添加了一个case "^"的操作,这一点就违反了开闭原则。

所以我们使用开始时介绍的工厂方法模式再来实现一次

3.工厂方法模式实现

先构建出一个IFactory的工厂接口

然后按照这个模板依次生成加减乘除,还有求幂的工厂实现类

在这里new 出来的OperationPow等等的实例,就是再简单方法工厂中的对应的继承了Operation抽象类的实现类

 最后在使用的时候,首先需要

1.根据自己的需求选择合适的工厂,然后通过工厂接口使用多态的形式来引用(选择合适的工厂类,通过工厂接口创建工厂对象。 目的:隔离工厂的创建细节,利用多态屏蔽具体实现

2.使用第一步产生的对象引用,调用对应工厂方法创建对象(使用工厂对象创建产品对象。 目的:通过工厂的 createOperation 方法,获得一个具体的产品对象

3.通过第二步创建的比如pow求幂对象,来使用对应的方法求幂即可(使用创建好的产品对象,调用其业务功能方法。 目的:完成运算逻辑或业务功能(创造价值))

4.抽象工厂模式实现

假设你要开发一个支持:

  • 普通计算器(支持 + − × ÷、求幂)

  • 科学计算器(还支持对数、三角函数等)

这时,一个运算符已经不能满足需求了,你现在想做的是:

一个“计算器族”中不仅有运算类,还有显示类、输入类等。

不同“族”的产品会组合使用。

当系统中有多个产品族(比如运算类、显示类)需要统一管理与创建时,抽象工厂模式是最佳选择。

抽象工厂模式的核心思想是“工厂的工厂”。这意味着,不同的工厂可以创建不同的对象家族,而不是单个对象。这些工厂可以是具体的类,也可以是抽象类或接口。客户端使用这些工厂接口创建对象,而无需知道底层的实现细节。

在 Java 中,抽象工厂模式通常通过一个抽象工厂接口来定义,并通过具体工厂类实现。这个接口通常包含多个方法,每个方法都返回一个特定类型的产品。具体工厂类将实现这个接口,并创建相关产品的实例。

抽象产品接口(运算类)

public abstract class Operation {
    protected double numberA;
    protected double numberB;

    public void setNumberA(double numberA) { this.numberA = numberA; }
    public void setNumberB(double numberB) { this.numberB = numberB; }

    public abstract double getResult();
}

抽象产品接口(显示类)

public interface Display {
    void show(double result);
}

抽象工厂接口

public interface CalculatorFactory {
    Operation createOperation(String opType);
    Display createDisplay();
}

普通计算器工厂(一个产品族)

public class SimpleCalculatorFactory implements CalculatorFactory {
    @Override
    public Operation createOperation(String opType) {
        return switch (opType) {
            case "+" -> new OperationAdd();
            case "-" -> new OperationSub();
            case "*" -> new OperationMul();
            case "/" -> new OperationDiv();
            case "^" -> new OperationPow();
            default -> throw new IllegalArgumentException("不支持该运算");
        };
    }

    @Override
    public Display createDisplay() {
        return new SimpleDisplay(); // 控制台输出
    }
}

科学计算器工厂(另一个产品族)

public class ScientificCalculatorFactory implements CalculatorFactory {
    @Override
    public Operation createOperation(String opType) {
        return switch (opType) {
            case "log" -> new OperationLog();
            case "sin" -> new OperationSin();
            default -> throw new IllegalArgumentException("不支持该科学运算");
        };
    }

    @Override
    public Display createDisplay() {
        return new ScientificDisplay(); // GUI 方式展示
    }
}

产品实现类举例

public class OperationAdd extends Operation {
    public double getResult() { return numberA + numberB; }
}

public class OperationPow extends Operation {
    public double getResult() { return Math.pow(numberA, numberB); }
}

public class SimpleDisplay implements Display {
    public void show(double result) {
        System.out.println("计算结果是:" + result);
    }
}

客户端使用

public class Main {
    public static void main(String[] args) {
        CalculatorFactory factory = new SimpleCalculatorFactory();
        Operation operation = factory.createOperation("^");
        operation.setNumberA(2);
        operation.setNumberB(10);
        double result = operation.getResult();

        Display display = factory.createDisplay();
        display.show(result);  // 输出:计算结果是:1024.0
    }
}
模式类型 特点说明
简单工厂模式 所有创建逻辑集中在一个类里,违反开闭原则
工厂方法模式 每种产品一个工厂,扩展方便
抽象工厂模式 一组“相关产品”一起创建(如操作类 + 显示类)

5.工厂方法和抽象工厂有何不同

Java 中的工厂方法模式和抽象工厂模式都是创建型设计模式,它们的主要目的都是封装对象的创建过程,将对象的创建和使用分离开来,简单工厂是工厂方法模式的特例。

  1. 创建对象的方式不同:
  • 工厂方法模式:工厂方法模式通过定义一个工厂接口和多个具体工厂类来实现对象的创建。每个具体工厂类都实现了工厂接口,并负责创建一类产品对象。客户端通过工厂接口来创建产品对象,具体的产品类和工厂类都可以在运行时动态切换。
  • 抽象工厂模式:抽象工厂模式定义了多个工厂接口和多个产品族接口,每个工厂接口负责创建一类产品族对象,每个产品族接口负责定义一类产品对象。具体工厂类实现工厂接口并负责创建一类产品族对象,具体产品类实现产品族接口并负责创建一类产品对象。客户端通过工厂接口和产品族接口来创建产品对象,具体的产品族和工厂类都可以在运行时动态切换。

2. 创建的对象类型不同:

  • 工厂方法模式:工厂方法模式适用于创建多种类型的产品对象。
  • 抽象工厂模式:抽象工厂模式适用于创建多个产品族的对象。

3. 代码结构不同:

  • 工厂方法模式:工厂方法模式通常只需要一个工厂接口和多个具体工厂类,客户端只需要调用工厂接口的方法即可创建对象。
  • 抽象工厂模式:抽象工厂模式需要定义多个工厂接口和产品族接口,每个工厂接口和产品族接口都需要对应多个具体实现类,代码结构更加复杂。

总结

简单工厂模式适用于创建单一类型的产品对象,工厂方法模式适用于创建多种类型的产品对象,而抽象工厂模式适用于创建多个产品族的对象。


网站公告

今日签到

点亮在社区的每一天
去签到