📜  抽象工厂模式

📅  最后修改于: 2021-09-10 02:54:12             🧑  作者: Mango

介绍

抽象工厂设计模式是创造模式的一种。抽象工厂模式几乎类似于工厂模式,被认为是对工厂模式的另一层抽象。抽象工厂模式围绕创建其他工厂的超级工厂工作。

抽象工厂模式实现为我们提供了一个框架,允许我们创建遵循通用模式的对象。因此,在运行时,抽象工厂与任何可以创建所需类型对象的具体工厂相结合。

让我们看看抽象工厂模式的 GOF 表示:

抽象工厂设计模式的 UML 类图示例。

  • AbstractFactory :为创建抽象产品对象的操作声明一个接口。
  • ConcreteFactory :实现在 AbstractFactory 中声明的操作以创建具体的产品对象。
  • Product :定义了一个由相应的具体工厂创建的产品对象,并实现了 AbstractProduct 接口。
  • Client :仅使用 AbstractFactory 和 AbstractProduct 类声明的接口。

抽象工厂提供了用于创建相关或依赖对象系列的接口,而无需指定它们的具体类。

客户端软件创建抽象工厂的具体实现,然后使用通用接口创建属于对象系列的具体对象。
客户端不知道也不关心它从每个具体工厂中获得哪些具体对象,因为它只使用其产品的通用接口。

因此,有了抽象工厂模式的这个想法,我们现在将尝试创建一个有助于创建相关对象的设计。

执行

举个例子,假设我们要建立一个全球汽车工厂。如果是工厂设计模式,那么它适用于单一位置。但是对于这种模式,我们需要多个位置和一些关键的设计更改。

我们需要每个地方的汽车工厂,如 IndiaCarFactory、USACarFactory 和 DefaultCarFactory。现在,我们的应用程序应该足够智能,可以识别使用它的位置,因此我们应该能够使用合适的汽车工厂,甚至不知道将在内部使用哪个汽车工厂实现。这也使我们免于有人为特定位置调用错误的工厂。

在这里,我们需要另一层抽象来识别位置并在内部使用正确的汽车工厂实现,而无需向用户提供任何提示。这正是抽象工厂模式用来解决的问题。

// Java Program to demonstrate the 
// working of Abstract Factory Pattern
  
enum CarType
{
    MICRO, MINI, LUXURY
}
  
abstract class Car
{
    Car(CarType model, Location location)
    {
        this.model = model;
        this.location = location;
    }
   
    abstract void construct();
   
    CarType model = null;
    Location location = null;
   
    CarType getModel()
    {
        return model;
    }
   
    void setModel(CarType model)
    {
        this.model = model;
    }
   
    Location getLocation()
    {
        return location;
    }
   
    void setLocation(Location location)
    {
        this.location = location;
    }
   
    @Override
    public String toString()
    {
        return "CarModel - "+model + " located in "+location;
    }
}
  
class LuxuryCar extends Car
{
    LuxuryCar(Location location)
    {
        super(CarType.LUXURY, location);
        construct();
    }
    @Override
    protected void construct()
    {
        System.out.println("Connecting to luxury car");
    }
}
  
class MicroCar extends Car
{
    MicroCar(Location location)
    {
        super(CarType.MICRO, location);
        construct();
    }
    @Override
    protected void construct()
    {
        System.out.println("Connecting to Micro Car ");
    }
}
  
class MiniCar extends Car
{
    MiniCar(Location location)
    {
        super(CarType.MINI,location );
        construct();
    }
      
    @Override
    void construct()
    {
        System.out.println("Connecting to Mini car");
    }
}
  
enum Location
{
  DEFAULT, USA, INDIA
}
  
class INDIACarFactory
{
    static Car buildCar(CarType model)
    {
        Car car = null;
        switch (model)
        {
            case MICRO:
                car = new MicroCar(Location.INDIA);
                break;
              
            case MINI:
                car = new MiniCar(Location.INDIA);
                break;
                  
            case LUXURY:
                car = new LuxuryCar(Location.INDIA);
                break;
                  
                default:
                break;
              
        }
        return car;
    }
}
  
class DefaultCarFactory
{
    public static Car buildCar(CarType model)
    {
        Car car = null;
        switch (model)
        {
            case MICRO:
                car = new MicroCar(Location.DEFAULT);
                break;
              
            case MINI:
                car = new MiniCar(Location.DEFAULT);
                break;
                  
            case LUXURY:
                car = new LuxuryCar(Location.DEFAULT);
                break;
                  
                default:
                break;
              
        }
        return car;
    }
}
  
  
class USACarFactory
{
    public static Car buildCar(CarType model)
    {
        Car car = null;
        switch (model)
        {
            case MICRO:
                car = new MicroCar(Location.USA);
                break;
              
            case MINI:
                car = new MiniCar(Location.USA);
                break;
                  
            case LUXURY:
                car = new LuxuryCar(Location.USA);
                break;
                  
                default:
                break;
              
        }
        return car;
    }
}
  
  
  
class CarFactory
{
    private CarFactory() 
    {
          
    }
    public static Car buildCar(CarType type)
    {
        Car car = null;
        // We can add any GPS Function here which
        // read location property somewhere from configuration
        // and use location specific car factory
        // Currently I'm just using INDIA as Location
        Location location = Location.INDIA; 
          
        switch(location)
        {
            case USA:
                car = USACarFactory.buildCar(type);
                break;
                  
            case INDIA:
                car = INDIACarFactory.buildCar(type);
                break;
                      
            default:
                car = DefaultCarFactory.buildCar(type);
  
        }
          
        return car;
  
    }
}
  
class AbstractDesign 
{
    public static void main(String[] args)
    {
        System.out.println(CarFactory.buildCar(CarType.MICRO));
        System.out.println(CarFactory.buildCar(CarType.MINI));
        System.out.println(CarFactory.buildCar(CarType.LUXURY));
    }
}

输出 :

Connecting to Micro Car 
CarModel - MICRO located in INDIA
Connecting to Mini car
CarModel - MINI located in INDIA
Connecting to luxury car
CarModel - LUXURY located in INDIA

区别

  • “工厂方法”和“抽象工厂”的主要区别在于工厂方法是单个方法,抽象工厂是一个对象。
  • 工厂方法只是一个方法,它可以在子类中被覆盖,而抽象工厂是一个具有多个工厂方法的对象。
  • 工厂方法模式使用继承并依赖子类来处理所需的对象实例化。

好处

当客户端不确切知道要创建什么类型时,此模式特别有用。

  • 具体类的隔离:抽象工厂模式可帮助您控制应用程序创建的对象类。由于工厂封装了创建产品对象的职责和过程,因此它将客户与实现类隔离开来。客户端通过它们的抽象接口操作实例。产品类名在具体工厂的实现中是隔离的;它们不会出现在客户端代码中。
  • 轻松交换产品系列:具体工厂的类在应用程序中只出现一次,也就是它被实例化的地方。这使得更改应用程序使用的具体工厂变得容易。只需更换混凝土工厂即可使用各种产品配置。由于抽象工厂创建了完整的产品系列,因此整个产品系列会立即发生变化。
  • 促进产品之间的一致性:当一个系列中的产品对象设计为协同工作时,应用程序一次只使用一个系列的对象很重要。 AbstractFactory 使这很容易执行。

缺点

  • 难以支持新型产品:扩展抽象工厂以生产新型产品并不容易。那是因为 AbstractFactory 接口修复了可以创建的产品集。支持新类型的产品需要扩展工厂接口,这涉及更改 AbstractFactory 类及其所有子类。

笔记 :
在某种程度上,上面的例子也是基于像 uber 和 ola 这样的出租车如何大规模运作的。