Статьи

Решите проблемы дизайна, используя Factory Pattern

Шаблон проектирования фабрики является одним из наиболее часто используемых шаблонов в объектно-ориентированной среде. Это снова из категории шаблонов Creational Design, то есть все о создании объектов.

В некоторых случаях создание объекта является сложным и может потребовать некоторого уровня абстракции, чтобы клиентский код не знал об этих сложностях и деталях внутренней реализации. Могут быть сценарии, в которых создание объекта разбросано и повторяется в различных частях кода. Шаблон Factory решает эти проблемы, определяя интерфейс, который специально создает объект, но дает гибкость классам реализации для выбора того, какой класс создавать.

Определение:
Шаблон метода Factory предназначен для определения интерфейса для создания объектов, но делегирует создание объекта подклассам.

Задача:
Глядя на постановку задачи, цель должна быть:

  • Клиент должен не знать об экземпляре объекта
  • Клиент должен получить доступ к объектам через общий интерфейс.
Ты знаешь?
Шаблон проектирования фабричного метода обычно используется в различных средах, таких как Struts, Spring, Apache в сочетании с шаблоном проектирования декоратора. Существуют различные шаблоны J2EE, основанные на этом шаблоне Factory, например шаблон DAO.

Какой принцип объектно-ориентированного проектирования используется в шаблоне Factory?

Инкапсуляция: потому что она инкапсулирует код создания от клиента. И, очевидно, вы можете думать, что преимущества инкапсуляции также применимы для этого шаблона, такие как слабая связь и сцепление.

Практический пример:

Рассмотрим швейную фабрику, которая производит различные виды одежды, такие как рубашка, брюки. Потребители могут запросить необходимые типы одежды через фабрику. Однако с точки зрения потребителя они совершенно не знают, кто создает этот объект. Они просто знают, что Фабрика предоставляет им необходимую одежду.

Постановка задачи:

Это стандартная практика, когда объекты создаются путем вызова ключевого слова «new». Представьте себе сценарий, когда в клиентском классе есть несколько случаев, и мы вызываем несколько новых ключевых слов для создания новых объектов.

1
2
3
4
5
if (selection.equalsIgnoreCase("Trouser")) {
   return new Trouser();
  } else if (selection.equalsIgnoreCase("Shirt")) {
   return new Shirt();
  }

Если нам теперь нужно добавить куртку или свитер, мы должны продолжать изменять код клиента и дополнительно добавлять новое ключевое слово. Это создает зависимость от клиентского кода и, в свою очередь, затрудняет его поддержку.

Другая проблема заключается в том, что клиентское приложение должно знать, сколько типов конкретных классов доступно заранее. Позже, если нам нужно добавить еще один конкретный класс, например, свитер или куртку, код клиента должен быть изменен и перекомпилирован.

Решение:
Для решения вышеуказанных проблем можно явно использовать фабричный шаблон.

  • Первая проблема доступа к слишком большому количеству новых ключевых слов может быть решена с помощью класса Factory.
  • Вторую проблему можно решить с помощью интерфейса, который будут реализовывать конкретные классы, и клиент всегда будет указывать на класс интерфейса, а не на конкретные классы. Таким образом, клиент полностью не будет знать о различных типах конкретных классов, которые потребуются.
Что такое интерфейс?
Интерфейс в Java — это коллекция определений методов без реализации. Класс, который реализует интерфейс, должен обеспечивать реализацию и должен реализовывать все методы, описанные в интерфейсе. Интерфейс — это контракт, который сообщает классам, что должно быть сделано, и классы сами решают, как их можно реализовать.

1
2
3
interface Bounceable {
      void setBounce();
}

Приведенная ниже диаграмма классов даст полный обзор реализации Factory Pattern:

Диаграмма классов фабричного образца

Давайте рассмотрим пример кода для реализации Factory Pattern:

GarmentType.java
1
2
3
public interface GarmentType {
 String print();
}
Trouser.java
1
2
3
4
5
6
7
8
public class Trouser implements GarmentType {
 @Override
 public String print() {
  System.out.println("Trouser Created");
  return "Trouser";
 }
 
}
Shirt.java
1
2
3
4
5
6
7
public class Shirt implements GarmentType {
 @Override
 public String print() {
  System.out.println("Shirt Created");
  return "Shirt";
 }
}
GarmentFactory.java
01
02
03
04
05
06
07
08
09
10
public class GarmentFactory {
 public static GarmentType createGarments(String selection) {
  if (selection.equalsIgnoreCase("Trouser")) {
   return new Trouser();
  } else if (selection.equalsIgnoreCase("Shirt")) {
   return new Shirt();
  }
  throw new IllegalArgumentException("Selection doesnot exist");
 }
}
Client.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
public class Client {
 public static void main(String[] args) {
  System.out.println("Enter your selection:");
  BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
  String selection = null;
  try {
   selection = br.readLine();
  } catch (IOException e) {
   e.printStackTrace();
  }
  GarmentType objGarmentType = GarmentFactory.createGarments(selection);
  System.out.println(objGarmentType.print());
 }
}

Преимущество фабричного образца:

а) Этому клиенту не нужно знать о подклассе объектов, который требуется создать. Требуется ссылка на интерфейс и заводской объект.
б) Процессы создания объекта переносятся с клиента на фабрику и, таким образом, связывают код клиента с кодом создания объекта. Это, в свою очередь, поможет в повторном использовании, так как этот код может использоваться другими клиентами.
c) Шаблон Factory также помогает в масштабируемости приложения, поскольку клиентский код относится только к интерфейсу, и мы можем добавить больше продуктов, реализующих интерфейс, без внесения множества изменений в клиентский код.
d) Удобство сопровождения кода полезно, если приложение использует шаблон Factory, поскольку создание объекта централизовано.

Ссылка: Решите проблемы дизайна, используя Factory Pattern от нашего партнера JCG Майнака Госвами в блоге Idiotechie .