Рубрики
Без рубрики

Расшифруйте Абстрактный Шаблон Дизайна Фабрики

Шаблон творческого дизайна Абстрактный Шаблон конструктора фабрики, когда его использовать… С тегом java, дизайн, архитектура, шаблон проектирования.

Шаблон Творческого Дизайна

  1. Абстрактная фабрика
  2. Шаблон строителя

Когда использовать

  • Для поддержки семейств связанных или зависимых объектов.
  • Для инкапсуляции зависимостей платформы, чтобы сделать приложение переносимым.
  • Чтобы клиентский код не использовал оператор ‘new’.
  • Чтобы легко поменять базовую платформу с минимальными изменениями.

Намерение

Предоставляет интерфейс для создания семейств связанных или зависимых объектов без указания их конкретных классов.

Компоненты

  • Абстрактный фабричный класс (общедоступный)
  • Заводские реализации для различных семейств (защищенные)
  • Интерфейсы для различных продуктов (общедоступные)
  • Набор реализаций продуктов для различных семейств (защищенных)

Структура

Реализация

1 Определите интерфейсы для различных типов продуктов/объектов. У каждой семьи будут все эти части.

package com.gaurav.abstractfactory;

public interface Engine {

  public void design();
  public void manufacture();
  public void test();

}
package com.gaurav.abstractfactory;

public interface Tyre {

  public void design();
  public void manufacture();

}

2 Создайте наборы подклассов реализации для вышеуказанных интерфейсов. Классы защищены от доступа, чтобы запретить создание экземпляров в клиентских модулях с использованием оператора ‘new’.

package com.gaurav.abstractfactory;

class CarEngine implements Engine {

  @Override
  public void design() {
    System.out.println("Designing Car Engine");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Car Engine");
  }

  @Override
  public void test() {
    System.out.println("Testing Car Engine");
  }

}
package com.gaurav.abstractfactory;

class TruckEngine implements Engine {

  @Override
  public void design() {
    System.out.println("Designing Truck Engine");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Truck Engine");
  }

  @Override
  public void test() {
    System.out.println("Testing Truck Engine");
  }

}
package com.gaurav.abstractfactory;

class CarTyre implements Tyre {

  @Override
  public void design() {
    System.out.println("Designing Car Tyre");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Car Tyre");
  }

}
package com.gaurav.abstractfactory;

class TruckTyre implements Tyre {

  @Override
  public void design() {
    System.out.println("Designing Truck Tyre");
  }

  @Override
  public void manufacture() {
    System.out.println("Manufacturing Truck Tyre");
  }

}

3 Создайте абстрактный фабричный класс с фабричным методом ‘getFactory()’. Клиенты могут использовать этот метод, чтобы получить для объекта требуемую фабрику. В этом примере используются как одноэлементные, так и фабричные шаблоны методов для лучшего проектирования.

package com.gaurav.abstractfactory;

public abstract class Factory {

  /* Singleton Factory objects */
  private static Factory carFactory = null;
  private static Factory truckFactory = null;

  public abstract Engine getEngine();
  public abstract Tyre getTyre();

  /*
   * This is the factory method exposed to the client.
   * Client requests for a factory instance by passing the type.
   * Client does not need to know about which & how
   * object is created internally.
   */
  public static Factory getFactory(String vehicleType)
      throws UnknownVehicleException {

    if (vehicleType == null) {
      return null;
    }

    Factory factory = null;
    switch (vehicleType) {
      case "car":
        if (carFactory == null)
          carFactory = new CarFactory();
        factory = carFactory;
        break;
      case "truck":
        if (truckFactory == null)
          truckFactory = new TruckFactory();
        factory = truckFactory;
        break;
      default:
        throw new UnknownVehicleException();
    }

    return factory;
  }
}

4 Создайте заводские реализации. Классы защищены, чтобы запретить прямой доступ в клиентских модулях.

package com.gaurav.abstractfactory;

class CarFactory extends Factory {

  @Override
  public Engine getEngine() {
    return new CarEngine();
  }

  @Override
  public Tyre getTyre() {
    return new CarTyre();
  }

}
package com.gaurav.abstractfactory;

public class TruckFactory extends Factory {

  TruckFactory() {}

  @Override
  public Engine getEngine() {
    return new TruckEngine();
  }

  @Override
  public Tyre getTyre() {
    return new TruckTyre();
  }

}

5 Код клиента. Клиент имеет доступ только к абстрактному заводскому классу и интерфейсам.

package com.gaurav.client;

import java.util.Scanner;

import com.gaurav.abstractfactory.Engine;
import com.gaurav.abstractfactory.Factory;
import com.gaurav.abstractfactory.Tyre;
import com.gaurav.abstractfactory.UnknownVehicleException;

public class AbstractFactoryClient {

  public static void main(String[] args) {

    Scanner in = new Scanner(System.in);
    String vehicleType = in.nextLine().toLowerCase();

    /* Get the factory instance */
    Factory factory;
    try {
      factory = Factory.getFactory(vehicleType);

      /* Get the Engine from the factory */
      Engine engine = factory.getEngine();
      engine.design();
      engine.manufacture();
      engine.test();

      /* Get the Tyre from the factory */
      Tyre tyre = factory.getTyre();
      tyre.design();
      tyre.manufacture();

    } catch (UnknownVehicleException e) {
      System.out.println("Invalid vehicle type entered!");
    }

    in.close();
  }

}

Выход

[input1]
    Car
[output1]
    Designing Car Engine
    Manufacturing Car Engine
    Testing Car Engine
    Designing Car Tyre
    Manufacturing Car Tyre

[input2]
    Bus
[output2]
    Invalid vehicle type entered!

Выгоды

  • Слабо связанный код.
  • Абстрактная фабрика обеспечивает единую точку доступа для всех продуктов семейства.
  • Новое семейство продуктов может быть легко поддержано.

Недостатки

  • Большее количество уровней абстракции увеличивает сложность.
  • Если есть какие-либо изменения в какой-либо базовой детали одной фабрики, возможно, потребуется изменить интерфейс для всех фабрик.

Примеры из Реального мира

Предоставление доступа к данным из двух разных источников данных (например, базы данных SQL и XML-файла). У вас есть два разных класса доступа к данным (шлюз к хранилищу данных). Оба наследуются от базового класса, который определяет общие методы, которые должны быть реализованы (например, Load, Save, Delete). Какой источник данных должен использоваться, не должен изменять способ получения клиентским кодом своего класса доступа к данным. Ваша абстрактная фабрика знает, какой источник данных должен использоваться, и возвращает соответствующий экземпляр по запросу. Фабрика возвращает этот экземпляр в качестве типа базового класса.

Примеры программного обеспечения

Внедрение зависимостей

Примеры Java SDK

javax.xml.синтаксические анализаторы. DocumentBuilderFactory newInstance() javax.xml.transform. TransformerFactory newInstance() javax.xml.xpath. XPathFactory newInstance()

Надеюсь, вам это понравится. Хотелось бы услышать ваши мысли об этом шаблоне дизайна.

Давайте выпьем кофе

Оригинал: “https://dev.to/gauravratnawat/abstract-factory-haf”