原文: https://howtodoinjava.com/design-patterns/creational/abstract-factory-pattern-in-java/

抽象工厂模式是又一个创造型设计模式,并且被视为工厂模式的另一抽象层。 在本教程中,我们将扩展工厂模式中讨论的汽车工厂问题的范围。 我们将通过扩大汽车工厂的范围来学习何时使用工厂模式,然后通过抽象工厂模式解决扩展的范围。

  1. Table of Contents
  2. 1\. Design global car factory using abstract factory pattern
  3. 2\. Abstract factory pattern based solution
  4. 3\. Abstract factory pattern implementation
  5. 4\. Summary

1.使用抽象工厂模式设计全局汽车工厂

在“ 工厂设计模式”中,我们讨论了如何针对各种汽车模型类型以及其包含在汽车制造过程中的附加逻辑来抽象汽车制造过程。 现在,想象一下我们的汽车制造商是否决定走向全局。

为了支持全局运营,我们将需要增强系统以支持不同国家/地区的不同汽车制造风格。 例如,在某些国家/地区中,方向盘位于左侧,而在某些国家/地区中,其方向盘位于右侧。 在汽车的不同部分及其制造过程中可能还会存在更多此类差异。

为了描述抽象工厂模式,我们将考虑三种制造方式 - 所有其他国家/地区的美国亚洲默认。 支持多个位置将需要进行关键的设计更改。

首先,我们需要在问题说明中指定的每个位置中都有汽车工厂。 即USACarFactoryAsiaCarFactoryDefaultCarFactory。 现在,我们的应用应该足够智能,可以识别使用的位置,因此我们应该能够使用适当的汽车工厂,甚至不知道内部将使用哪个汽车工厂实现。 这也可以避免我们为某个特定位置称呼错误的工厂。

因此,基本上,我们需要另一层抽象,它将识别位置并在内部使用正确的汽车工厂实现方式,甚至不会向用户提供任何提示。 这正是使用抽象工厂模式来解决的问题。

2.基于抽象工厂模式的解决方案

2.1 包图

使用抽象工厂模式参与全局汽车工厂设计的类的类图。

抽象工厂模式解释 - 图1

2.2 时序图

此图显示了CarFactory工厂类背后的类与抽象之间的交互。

抽象工厂模式解释 - 图2

请注意,我已设计解决方案以完全隐藏最终用户的位置详细信息。 因此,我没有直接暴露任何特定于位置的工厂。

在替代解决方案中,我们可以首先基于location参数获取特定于位置的工厂,然后在抽象引用上使用其buildCar()方法来构建实际的汽车实例。

3.抽象工厂模式实现

Java 类为全局汽车工厂实现抽象工厂模式。

首先,我们必须为不同的位置编写所有独立的汽车工厂。 为了支持特定于位置的功能,请首先使用另一个属性location修改Car.java类。

  1. public abstract class Car {
  2. public Car(CarType model, Location location){
  3. this.model = model;
  4. this.location = location;
  5. }
  6. protected abstract void construct();
  7. private CarType model = null;
  8. private Location location = null;
  9. //getters and setters
  10. @Override
  11. public String toString() {
  12. return "Model- "+model + " built in "+location;
  13. }
  14. }

这增加了创建另一个用于存储不同位置的枚举的工作。

  1. public enum Location {
  2. DEFAULT, USA, ASIA
  3. }

所有汽车类型还将具有附加的location属性。 我们只为豪华车而写。 小轿车和轿车也是如此。

  1. public class LuxuryCar extends Car
  2. {
  3. public LuxuryCar(Location location)
  4. {
  5. super(CarType.LUXURY, location);
  6. construct();
  7. }
  8. @Override
  9. protected void construct() {
  10. System.out.println("Building luxury car");
  11. //add accessories
  12. }
  13. }

到目前为止,我们已经创建了基本类。 现在让我们拥有不同的汽车工厂,这是抽象工厂模式背后的核心思想。

  1. public class AsiaCarFactory
  2. {
  3. public static Car buildCar(CarType model)
  4. {
  5. Car car = null;
  6. switch (model)
  7. {
  8. case SMALL:
  9. car = new SmallCar(Location.ASIA);
  10. break;
  11. case SEDAN:
  12. car = new SedanCar(Location.ASIA);
  13. break;
  14. case LUXURY:
  15. car = new LuxuryCar(Location.ASIA);
  16. break;
  17. default:
  18. //throw some exception
  19. break;
  20. }
  21. return car;
  22. }
  23. }
  1. public class DefaultCarFactory
  2. {
  3. public static Car buildCar(CarType model)
  4. {
  5. Car car = null;
  6. switch (model)
  7. {
  8. case SMALL:
  9. car = new SmallCar(Location.DEFAULT);
  10. break;
  11. case SEDAN:
  12. car = new SedanCar(Location.DEFAULT);
  13. break;
  14. case LUXURY:
  15. car = new LuxuryCar(Location.DEFAULT);
  16. break;
  17. default:
  18. //throw some exception
  19. break;
  20. }
  21. return car;
  22. }
  23. }
  1. public class USACarFactory
  2. {
  3. public static Car buildCar(CarType model)
  4. {
  5. Car car = null;
  6. switch (model)
  7. {
  8. case SMALL:
  9. car = new SmallCar(Location.USA);
  10. break;
  11. case SEDAN:
  12. car = new SedanCar(Location.USA);
  13. break;
  14. case LUXURY:
  15. car = new LuxuryCar(Location.USA);
  16. break;
  17. default:
  18. //throw some exception
  19. break;
  20. }
  21. return car;
  22. }
  23. }

好吧,现在我们所有 3 个不同的汽车工厂。 现在,我们必须抽象化访问这些工厂的方式。

  1. public class CarFactory
  2. {
  3. private CarFactory() {
  4. //Prevent instantiation
  5. }
  6. public static Car buildCar(CarType type)
  7. {
  8. Car car = null;
  9. Location location = Location.ASIA; //Read location property somewhere from configuration
  10. //Use location specific car factory
  11. switch(location)
  12. {
  13. case USA:
  14. car = USACarFactory.buildCar(type);
  15. break;
  16. case ASIA:
  17. car = AsiaCarFactory.buildCar(type);
  18. break;
  19. default:
  20. car = DefaultCarFactory.buildCar(type);
  21. }
  22. return car;
  23. }
  24. }

我们已经完成编写代码。 现在,让我们测试一下工厂和汽车。

  1. public class TestFactoryPattern
  2. {
  3. public static void main(String[] args)
  4. {
  5. System.out.println(CarFactory.buildCar(CarType.SMALL));
  6. System.out.println(CarFactory.buildCar(CarType.SEDAN));
  7. System.out.println(CarFactory.buildCar(CarType.LUXURY));
  8. }
  9. }

程序输出:

  1. Output: (Default location is Asia)
  2. Building small car
  3. Model- SMALL built in ASIA
  4. Building sedan car
  5. Model- SEDAN built in ASIA
  6. Building luxury car
  7. Model- LUXURY built in ASIA

4.总结

我们已经看到了工厂模式的用例场景,因此,每当需要一组工厂上的另一个抽象级别时,都应考虑使用抽象工厂模式。 工厂模式与抽象工厂模式之间可能只是这些区别

您已经可以更深入地研究 JDK 分发中的抽象工厂的不同实时示例

还有其他类似的示例,但是需要对抽象工厂设计模式有所了解,这是您到目前为止必须已经掌握的。

学习愉快!

参考文献:

抽象工厂 – 维基百科