软件设计模式系列之四——简单工厂模式

1 模式的定义

简单工厂模式(Simple Factory Pattern)是一种创建型设计模式,用于对象的创建,它属于工厂模式的一种。简单工厂模式的主要目标是封装对象的创建过程,使客户端代码与具体类的实例化解耦,从而提高代码的可维护性和可扩展性。

简单工厂模式定义了一个工厂类,该工厂类负责根据客户端的需求创建不同类型的对象,而客户端只需提供一个参数或者条件,工厂类就能返回相应的具体对象实例。

2 举例说明

利用富士康代工生产小米手机、华为手机为例来说明一下简单工厂模式,其中

富士康工厂就是简单工厂,负责根据客户(小米和华为)的要求来制造手机。

小米手机和 华为手机 是具体的产品,它们有不同的特性和功能,但都属于手机产品。

在这个例子中,富士康工厂就像是一个手机制造工厂,客户(小米和华为)只需要向工厂提出订单(传递一个参数或条件,例如手机品牌),工厂根据客户的要求生产出相应的手机产品。客户不需要了解手机制造的具体细节,只需与工厂交互即可。这种方式将手机的创建过程与客户代码解耦,使得客户端更加简洁,并且富士康工厂可以根据市场需求轻松地生产不同品牌的手机,而不需要修改客户端代码。

简单工厂模式在这个例子中帮助了富士康工厂代工制造手机,客户只需要告诉工厂需要哪种手机,而无需关心手机的具体制造过程,这体现了简单工厂模式的核心思想,即将对象的创建与客户端代码解耦,从而提高了灵活性和可维护性。

3 结构

简单工厂模式的结构主要包括以下三个关键元素:

  • 具体产品类(Concrete Products)

具体产品类是工厂类创建的对象类型,它们共享一个公共的抽象产品类或接口。每个具体产品类实现了抽象产品类或接口中定义的方法,以提供特定的功能和行为。

  • 工厂类(Factory)

工厂类是简单工厂模式的核心部分,负责根据客户端的请求创建具体产品对象。工厂类通常包含一个或多个工厂方法,每个工厂方法用于创建不同类型的具体产品对象。工厂类的目标是封装对象的创建逻辑,使客户端免于了解具体产品的构造过程。

  • 客户端(Client)

客户端是使用简单工厂模式的代码部分,负责向工厂类发送请求以获取所需的具体产品对象。客户端通常不直接实例化具体产品对象,而是通过工厂类来获取对象。

简单工厂模式的关键思想是将对象的创建和客户端解耦,客户端只需要知道如何使用工厂类来获取所需的对象,而无需关心对象的具体创建过程。这种模式有助于提高代码的可维护性和可扩展性,因为它允许在不修改客户端代码的情况下添加新的具体产品类。

4 实现步骤

简单工厂模式的实现步骤如下:

4.1 定义抽象产品类(Abstract Product)

首先,定义一个抽象产品类或接口,它声明了具体产品类必须实现的方法。这个抽象产品类将统一具体产品的接口。

4.2 创建具体产品类(Concrete Products)

为每个具体产品创建一个相应的类,这些类应该实现抽象产品类中定义的方法。

具体产品类表示不同类型的对象,具体产品的特性和行为由这些类来定义。

4.3 创建工厂类(Factory)

创建一个工厂类,该工厂类负责对象的创建。

在工厂类中定义一个或多个工厂方法,用于根据客户端的请求创建具体产品对象。

工厂方法通常会包括条件判断或者其他逻辑,以确定创建哪个具体产品对象。

4.4 客户端使用工厂类

客户端不直接实例化具体产品对象,而是通过调用工厂类的方法来获取所需的对象。

客户端需要知道如何使用工厂类,以及如何传递参数或条件给工厂类来获取合适的对象。

4.5 客户端调用工厂方法

客户端在需要具体产品对象的地方,调用工厂方法并传递必要的参数或条件。

工厂方法会根据参数或条件来创建并返回相应的具体产品对象。

总的来说,简单工厂模式通过将对象的创建逻辑封装在工厂类中,使客户端代码与具体产品的构造过程解耦,从而提高了代码的可维护性和可扩展性。客户端只需要关注如何使用工厂类来获取对象,而无需了解对象的创建细节。这种模式适用于那些对象的创建过程相对简单,不需要频繁变化的场景。

5 代码实现

首先,定义抽象手机类 AbstractMobile,其中只包含一个抽象方法 action

java 复制代码
public abstract class AbstractMobile {
    public abstract void action();
}

接下来,创建具体手机类 XiaomiMobileHuaweiMobile,它们分别继承自 AbstractMobile 并实现 action 方法:

java 复制代码
public class XiaomiMobile extends AbstractMobile {
    @Override
    public void action() {
        System.out.println("Xiaomi Mobile is performing an action.");
    }
}

public class HuaweiMobile extends AbstractMobile {
    @Override
    public void action() {
        System.out.println("Huawei Mobile is performing an action.");
    }
}

然后,创建工厂类 FuFactory,该工厂类包含一个方法 createMobile 用于根据客户端的需求创建具体产品对象:

java 复制代码
public class FuFactory {
    public static AbstractMobile createMobile(String brand) {
        if ("Xiaomi".equals(brand)) {
            return new XiaomiMobile();
        } else if ("Huawei".equals(brand)) {
            return new HuaweiMobile();
        } else {
            throw new IllegalArgumentException("Invalid brand. Supported brands are Xiaomi and Huawei.");
        }
    }
}

最后,客户端代码可以使用 FuFactory 来创建手机对象,并调用 action 方法:

java 复制代码
public class Main {
    public static void main(String[] args) {
        AbstractMobile xiaomiPhone = FuFactory.createMobile("Xiaomi");
        AbstractMobile huaweiPhone = FuFactory.createMobile("Huawei");

        xiaomiPhone.action();
        huaweiPhone.action();
    }
}

这段 Java 代码将输出以下结果:

Xiaomi Mobile is performing an action.
Huawei Mobile is performing an action.

这个示例中,我们定义了一个抽象方法 action,要求具体手机类必须实现该方法。通过简单工厂模式,我们成功地创建了 XiaomiMobileHuaweiMobile 对象,并在客户端代码中调用了 action 方法。这种方式可以确保每个具体手机类都必须提供一个特定的行为实现。

6 典型应用场景

简单工厂模式适用于以下应用场景:

需要根据条件创建不同对象的情况 :当系统中的某个类有多个子类,而客户端在不同情况下需要创建不同子类的对象时,可以使用简单工厂模式。通过简单工厂,客户端只需提供条件或参数,而无需了解对象的具体构造过程。

对象的创建过程相对简单 :如果对象的创建逻辑相对简单,不涉及复杂的初始化操作或依赖关系的管理,那么简单工厂模式是一个合适的选择。它有助于将创建逻辑集中在一个工厂类中,提高了代码的可维护性。

需要降低客户端和具体产品类之间的耦合度 :通过简单工厂模式,客户端代码与具体产品类之间的耦合度降低,因为客户端只需要与工厂类交互,而无需直接与具体产品类交互。这使得客户端更加灵活,能够轻松适应变化。

需要在系统中集中管理对象的创建逻辑 :如果希望在整个系统中集中管理对象的创建逻辑,可以使用简单工厂模式。这有助于在将来的维护和扩展中更容易地修改或添加新的产品类。

对象创建频率较低 :如果某种类型的对象在系统中的创建频率相对较低,而且不需要支持多态性,简单工厂模式可以满足需求,避免创建大量的工厂方法。

需要注意的是,虽然简单工厂模式有其优点,但它也有一些缺点,例如不符合开闭原则,因为每次添加新的产品类都需要修改工厂类,可能导致工厂类变得庞大。因此,在某些情况下,工厂方法模式或抽象工厂模式可能更适合处理对象的创建需求。选择适当的创建型模式取决于具体的项目需求和设计目标。

7 优缺点

简单工厂模式有一些优点和缺点,下面是简单工厂模式的主要优缺点:

优点:

  • 封装对象创建过程 :简单工厂模式将对象的创建过程封装在工厂类中,使客户端无需关心对象的具体构造过程,从而降低了客户端代码与具体产品类之间的耦合度。
  • 代码重用 :通过工厂类来创建对象,可以在不同的地方多次使用相同的创建逻辑,提高了代码的重用性。
  • 集中管理 :简单工厂模式将对象的创建逻辑集中管理,有助于在系统中统一管理对象的创建,便于维护和修改。
  • 客户端简化 :客户端代码只需要与工厂类交互,无需了解具体产品类的细节,使客户端代码更加简洁和易懂。
  • 降低错误风险 :通过工厂类创建对象可以减少客户端可能出现的错误,因为客户端无法直接实例化具体产品类。

缺点:

  • 违反开闭原则 :每次添加新的具体产品类都需要修改工厂类,违反了开闭原则(对扩展开放,对修改关闭)。这可能导致工厂类变得庞大,影响代码的可维护性。
  • 不支持多态性 :简单工厂模式不能很好地支持多态性,因为所有的对象创建逻辑都集中在一个工厂类中,无法实现不同产品的不同工厂,导致无法使用多态来处理对象。
  • 工厂类职责过重 :随着具体产品类的增加,工厂类可能会变得庞大,包含大量的分支逻辑,不利于维护和扩展。
  • 可定制性有限 :简单工厂模式的定制性较低,因为工厂类负责所有产品的创建,如果需要针对不同客户定制不同的创建逻辑,可能不太适用。

8 类似模式

简单工厂模式是创建型设计模式之一,它通过一个工厂类来创建对象,客户端只需要提供一个参数或条件,工厂类就能返回相应的具体对象实例。这种模式适用于对象的创建相对简单的情况,但不支持多态性,每次添加新的产品类都需要修改工厂类。

工厂方法模式是建立在简单工厂模式的基础上的进一步抽象和扩展,它将对象的创建延迟到子类。每个具体产品类都有对应的工厂类,客户端通过与工厂接口或抽象类交互,具体产品的创建由子类工厂来完成。工厂方法模式支持多态性,允许不同的具体工厂创建不同的产品对象。

抽象工厂模式是创建型设计模式,它提供一个接口或抽象类来创建一系列相关或相互依赖的对象,而无需指定它们的具体类。抽象工厂模式通常用于创建一组有关联的产品,例如在制造电子设备时,可能需要同时创建屏幕、主板、CPU等相关组件,抽象工厂能够确保这些组件之间的兼容性。这种模式支持多态性,并且允许客户端使用不同的具体工厂创建一组相关的产品。

这三种模式之间的关系可以看作是一种逐步抽象和扩展的关系。简单工厂模式是最简单的工厂模式,它将对象的创建过程封装在一个工厂类中。工厂方法模式在简单工厂的基础上引入了多态性,通过子类工厂来创建不同类型的产品。抽象工厂模式进一步抽象,它用于创建一组相关的产品,并提供一种更高级别的抽象,以确保这些产品之间的协调和兼容。选择使用哪种工厂模式取决于具体的项目需求和设计目标。

9 小结

总的来说,简单工厂模式适用于对象创建过程相对简单且稳定的情况,能够有效地将对象的创建与使用分离,提高代码的可维护性和可扩展性。但在需要频繁添加新的具体产品类或需要支持多态性的情况下,工厂方法模式或抽象工厂模式可能更适合。选择适当的创建型模式取决于具体的项目需求和设计目标。