1. 概述

在这个教程中,我们将解释Java中的工厂设计模式。我们将介绍两种创造型设计模式:工厂方法和抽象工厂。然后,我们将通过一个示例来说明这些模式。

2. 工厂方法模式

首先,我们需要定义一个例子。我们正在为一家汽车制造商开发一个应用。最初,我们只有一个客户端,它使用燃油引擎制造车辆。为了遵循单一职责原则(SRP)和开闭原则(OCP),我们将使用工厂方法设计模式。

在深入代码之前,我们先定义一个默认的UML图来表示这个模式:

根据上述UML图,我们将定义与该模式相关的一些主要概念。工厂方法模式通过将产品的构造代码与使用此产品的代码分离,降低了代码的耦合度。这种设计使得我们可以独立于应用程序的其余部分提取产品的构造。此外,它允许在不破坏现有代码的情况下引入新产品。

现在让我们看看代码。在我们的示例应用中,首先定义MotorVehicle接口。该接口只有一个方法build(),用于构建特定的摩托车。接口的代码片段如下:

public interface MotorVehicle {
    void build();
}

下一步是实现MotorVehicle接口的具体类。我们将创建两种类型:MotorcycleCar。第一个的代码如下:

public class Motorcycle implements MotorVehicle {
    @Override
    public void build() {
        System.out.println("Build Motorcycle");
    }
}

对于Car类,代码如下:

public class Car implements MotorVehicle {
    @Override
    public void build() {
        System.out.println("Build Car");
    }
}

接着,我们将创建MotorVehicleFactory类。这个类负责创建每个新的车辆实例。它是一个抽象类,因为它的具体车辆是由其特定工厂创建的。该类的代码如下:

public abstract class MotorVehicleFactory {
    public MotorVehicle create() {
        MotorVehicle vehicle = createMotorVehicle();
        vehicle.build();
        return vehicle;
    }
    protected abstract MotorVehicle createMotorVehicle();
}

如你所见,create()方法调用抽象方法createMotorVehicle()来创建特定类型的摩托车。这就是为什么每个特定的摩托车工厂必须实现正确的MotorVehicle类型。我们之前已经实现了两种MotorVehicle类型:MotorcycleCar。现在我们将从基础类MotorVehicleFactory扩展以实现两者。

首先,MotorcycleFactory类:

public class MotorcycleFactory extends MotorVehicleFactory {
    @Override
    protected MotorVehicle createMotorVehicle() {
        return new Motorcycle();
    }
}

然后是CarFactory类:

public class CarFactory extends MotorVehicleFactory {
    @Override
    protected MotorVehicle createMotorVehicle() {
        return new Car();
    }
}

就这样;我们的应用已经按照工厂方法模式设计。现在我们可以添加任意多的新摩托车了。最后,我们需要使用UML表示法来看看最终设计的样子:

3. 抽象工厂模式

在第一次应用迭代后,两家新汽车品牌公司对我们的系统感兴趣:NextGenFutureVehicle。这些新公司不仅生产燃油车,还生产电动车。每家公司都有自己的车辆设计。

目前的系统无法处理这些新场景。我们必须支持电动车,并考虑每家公司都有自己的设计。为了解决这些问题,我们可以使用抽象工厂模式。当我们在使用工厂方法模式并需要将系统进化到更复杂系统时,通常会使用这个模式它将产品创建代码集中在一个地方。UML表示如下:

我们已经有了MotorVehicle接口。此外,还需要一个接口来表示电动车。新接口的代码片段如下:

public interface ElectricVehicle {
    void build();
}

接下来,我们将创建我们的抽象工厂。这个新类是抽象的,因为对象创建的责任将由具体的工厂承担。这种行为遵循了OCP和SRP。让我们看看类定义:

public abstract class Corporation {
    public abstract MotorVehicle createMotorVehicle();
    public abstract ElectricVehicle createElectricVehicle();
}

在为新公司创建具体工厂之前,我们必须为它们实现一些车辆。我们为FutureVehicle公司创建一些新类:

public class FutureVehicleMotorcycle implements MotorVehicle {
    @Override
    public void build() {
        System.out.println("Future Vehicle Motorcycle");
    }
}

然后是电动车实例:

public class FutureVehicleElectricCar implements ElectricVehicle {
    @Override
    public void build() {
        System.out.println("Future Vehicle Electric Car");
    }
}

我们将为NexGen公司做同样的事情:

public class NextGenMotorcycle implements MotorVehicle {
    @Override
    public void build() {
        System.out.println("NextGen Motorcycle");
    }
}

另外,另一个电动车的具体实现:

public class NextGenElectricCar implements ElectricVehicle {
    @Override
    public void build() {
        System.out.println("NextGen Electric Car");
    }
}

最后,我们准备好创建具体的工厂了。首先,我们从FutureVehicle工厂开始:

public class FutureVehicleCorporation extends Corporation {
    @Override
    public MotorVehicle createMotorVehicle() {
        return new FutureVehicleMotorcycle();
    }
    @Override
    public ElectricVehicle createElectricVehicle() {
        return new FutureVehicleElectricCar();
    }
}

现在另一个:

public class NextGenCorporation extends Corporation {
    @Override
    public MotorVehicle createMotorVehicle() {
        return new NextGenMotorcycle();
    }
    @Override
    public ElectricVehicle createElectricVehicle() {
        return new NextGenElectricCar();
    }
}

完成。我们使用抽象工厂模式完成了实现。这是我们自定义实现的UML图:

4. 工厂方法与抽象工厂比较

总之,工厂方法使用继承作为设计工具。而抽象工厂使用委托。前者依赖于子类实现,而基类提供期望的行为。此外,它是基于方法的,而不是基于类的。另一方面,抽象工厂应用于类。两者都遵循OCP和SRP,产生松散耦合的代码,并为代码库的未来变化提供更大的灵活性。创建代码集中在一处。

5. 结论

在这篇文章中,我们演示了工厂设计模式。我们介绍了工厂方法和抽象工厂,并通过一个示例展示了这两种模式的使用。最后,我们简要比较了两者。

如往常一样,完整的代码片段可以在GitHub上找到。