Head First 工厂模式

1 阅读4分钟

一、定义

使用工厂模式的目的是封装对象的创建,属于创建型设计模式,它有三个变种:简单工厂、工厂方法、抽象工厂。

1、简单工厂

有些人不认为它是工厂模式。下面就是一个简单工厂的示例。SimplePizzaFactory类只负责创建产品Pizza。通过入参type创建不同的产品。而Pizza是一个超类,它可以有多个子类。

public class SimplePizzaFactory {
    public static Pizza createPizza(String type) {
	Pizza pizza = null;
        if (type.equals("cheese")) {
            pizza = new CheesePizza();
        } else if (type.equals("calm")) {
            pizza = new CalmPizza();
        } else if (type.equals("veggle")) {
            pizza = new VegglePizza();
        }
        return pizza;
    }
}

2、工厂方法

定义:定义了一个创建对象的接口,但由子类决定要实例化的类是哪一个。工厂方法让类把实例化推迟到子类。。
工厂方法模式通过让子类决定该创建的对象是什么,来达到将对象创建的过程封装的目的。这样,客户程序中关于超类的代码就和子类对象创建代码解耦了。

abstract Product factoryMethod(String type);
  • 工厂方法是抽象abstract的,所以依赖子类来处理对象的创建。
  • 工厂方法必须返回一个产品Product。超类中定义的方法,通常使用到工厂方法的返回值。比如orderPizza()方法中使用createPizza()这个工厂方法返回的Pizza实例。
  • 工厂方法将客户(也就是超类中的代码,例如orderPizza())和实际创建具体产品的代码分割开来。
  • 工厂方法也可能需要参数(也可能不需要)来指定所要的产品。

让我们来看看这些类图,以了解有哪些组成元素。

无标题-2025-11-28-1637.png

工厂方法和创建者不一定总是抽象的。可以定义一个默认的工厂方法来产生某些具体的产品。这么一来,即使创建者没有任何子类,依然可以创建产品。

3、抽象工厂

定义:提供一个接口,用于创建相关或依赖对象的家族,而不需要明确指定具体类。
抽象工厂允许客户使用抽象的接口来创建一组相关的产品,而不需要知道实际产出的具体产品是什么。这样一来,客户就从具体的产品中被解耦。
让我们看看类图来了解其中的关系:

无标题-2025-11-28-1637.png

模式优点缺点区别实现
简单工厂违反对修改关闭原则。要新增\删除产品时,需要到工厂的创建产品方法中修改代码
工厂方法1. 遵循对修改关闭,对扩展开放的原则。1. 使用继承。2. 创建一个产品。利用工厂方法创建对象,需要扩展一个类,并覆盖它的工厂方法,通过子类来创建对象。
抽象工厂1. 可以把一群相关的产品集合起来要扩展相关的产品,必须改变接口以及所有子类1. 通过对象的组合。2. 创建整个产品家族。提供一个用来创建一个产品家族的抽象类型(也就是抽象工厂),这个工厂的子类定义了产生产品的方法。要想使用这个工厂,必须先实例化它,然后将它传入一些针对抽象类型所写的代码中。

1、工厂模式的优点

  • 将创建对象的代码集中在一个对象或方法中,可以避免代码的重复。
  • 代码易于维护和管理。
  • 将客户程序从具体类解耦。客户在实例化对象时,只会依赖于接口,而不是具体类。
  • 代码具有弹性,可以应对未来的扩展。

2、使用到的OO设计原则

  • 封装变化
  • 多用组合,少用继承
  • 针对接口编程,不针对实现编程
  • 为交互对象之间的松耦合设计而努力
  • 类应该对扩展开放,对修改关闭
  • 依赖倒置原则

二、使用场景

  1. 当需要创建产品家族和想让制造的相关产品集合起来时,可以使用抽象工厂模式。
  2. 把客户的代码从需要实例化的具体类中解耦时,使用工厂方法模式。
  3. 如果目前还不知道将来需要实例化哪些具体类时,使用工厂方法模式。

具体应用

华晟项目管理系统中,在创建项目时,需要同步创建不同的计划。 在创建项目的类型不同时,同步创建的计划也不同。

  1. 创建常规项目时,需要创建计划有:主计划、生产交付计划、验收计划、SOP计划。
  2. 创建部门项目时,需要创建计划有:主计划。
  3. 在项目的验收阶段,需要创建结算计划。