1. 概述
在这个教程中,我们将解释Java中的工厂设计模式。我们将介绍两种创造型设计模式:工厂方法和抽象工厂。然后,我们将通过一个示例来说明这些模式。
2. 工厂方法模式
首先,我们需要定义一个例子。我们正在为一家汽车制造商开发一个应用。最初,我们只有一个客户端,它使用燃油引擎制造车辆。为了遵循单一职责原则(SRP)和开闭原则(OCP),我们将使用工厂方法设计模式。
在深入代码之前,我们先定义一个默认的UML图来表示这个模式:
根据上述UML图,我们将定义与该模式相关的一些主要概念。工厂方法模式通过将产品的构造代码与使用此产品的代码分离,降低了代码的耦合度。这种设计使得我们可以独立于应用程序的其余部分提取产品的构造。此外,它允许在不破坏现有代码的情况下引入新产品。
现在让我们看看代码。在我们的示例应用中,首先定义MotorVehicle
接口。该接口只有一个方法build()
,用于构建特定的摩托车。接口的代码片段如下:
public interface MotorVehicle {
void build();
}
下一步是实现MotorVehicle
接口的具体类。我们将创建两种类型:Motorcycle
和Car
。第一个的代码如下:
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
类型:Motorcycle
和Car
。现在我们将从基础类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. 抽象工厂模式
在第一次应用迭代后,两家新汽车品牌公司对我们的系统感兴趣:NextGen
和FutureVehicle
。这些新公司不仅生产燃油车,还生产电动车。每家公司都有自己的车辆设计。
目前的系统无法处理这些新场景。我们必须支持电动车,并考虑每家公司都有自己的设计。为了解决这些问题,我们可以使用抽象工厂模式。当我们在使用工厂方法模式并需要将系统进化到更复杂系统时,通常会使用这个模式。它将产品创建代码集中在一个地方。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上找到。