Статьи

Шаблон фабричного метода в Java

В моем предыдущем посте о шаблонном шаблонном методе я показал, как можно использовать лямбда-выражения и методы по умолчанию . В этой статье я расскажу о шаблоне фабричного метода и узнаю, как можно использовать ссылки на методы, еще одну функцию, добавленную в Java 8 наряду с лямбда-выражениями .

Давайте рассмотрим интерфейс Vehicle и 2 его реализации, а именно Car и Vehicle .

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
interface Vehicle{
  public void drive();
  public void clean();
}
class Car implements Vehicle{
  @Override
  public void drive(){
    System.out.println("Driving a car...");
  }
 
  @Override
  public void clean(){
    System.out.println("Cleaning a car...");
  }
}
class Bus implements Vehicle{
  @Override
  public void drive(){
    System.out.println("Driving a Bus...");
  }
 
  @Override
  public void clean(){
    System.out.println("Cleaning a Bus...");
  }
}

И чтобы drive() и clean() Vehicle мы бы использовали VehicleDriver .

Реализация в Java 7 и ранее

Давайте рассмотрим реализацию и VehicleDriver с точки зрения Pre Java 8, то есть Java 7 и ранее.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
abstract class VehicleDriver{
  public abstract Vehicle getVehicle();
  public void driveVehicle(){
    getVehicle().drive();
  }
  public void cleanVehicle(){
    getVehicle().clean();
  }
}
class CarDriver extends VehicleDriver{
  @Override
  public Vehicle getVehicle(){
    return new Car();
  }
}
 
class BusDriver extends VehicleDriver{
  @Override
  public Vehicle getVehicle(){
    return new Bus();
  }
}

В приведенной выше реализации getVehicle() метод getVehicle() является фабричным методом, который переопределяется CarDriver и Busdriver для возврата экземпляров Car и Bus соответственно. Таким образом, программист будет больше VehicleDriver об использовании абстракции VehicleDriver и не должен VehicleDriver о его различных реализациях. Есть еще один связанный шаблон: Factory Pattern, который немного отличается от этого шаблона, и читатели не должны путать это с этим шаблоном. Хорошо, давайте быстро посмотрим, как это можно использовать, прежде чем перейти к варианту Java 8:

01
02
03
04
05
06
07
08
09
10
11
12
public class FactoryMethodPattern {
   public static void main(String[] args) {
 
    handleVehicle(new CarDriver());
    handleVehicle(new BusDriver());
  }
  static void handleVehicle(VehicleDriver2 vDriver){
    System.out.println("Handling a new vehicle. Pre lambda way");
    vDriver.driveVehicle();
    vDriver.cleanVehicle();
  }
}

Выход будет:

1
2
3
4
5
6
Handling a new vehicle. Pre lambda way
Driving a car...
Cleaning a car...
Handling a new vehicle. Pre lambda way
Driving a Bus...
Cleaning a Bus...

Использование Java 8

Во-первых, нам не нужен абстрактный VehicleDriver и его 2 различные реализации. Вместо этого мы используем интерфейсы с методами по умолчанию для создания абстракции VehicleDriver как показано ниже:

1
2
3
4
5
6
7
8
9
interface VehicleDriver{
    public Vehicle getVehicle();
    public default void driveVehicle(){
        getVehicle().drive();
    }
    public default void cleanVehicle(){
        getVehicle().clean();
    }  
}

Теперь давайте перейдем к интересной части — Использование ссылок на VehicleDriver вместо создания другой реализации VehicleDriver . Эти ссылки на метод обеспечивают способ для кода получить требуемый экземпляр класса Car или Bus без необходимости getVehicle() метод getVehicle() . Смущенный? Любопытно? Давайте посмотрим, как мы можем достичь этого:

01
02
03
04
05
06
07
08
09
10
11
12
public class FactoryMethodPatternLambda {
  public static void main(String[] args) {
 
    handleVehicle(Car::new);
    handleVehicle(Bus::new);
  }
  static void handleVehicle(VehicleDriver vDriver){
    System.out.println("Handling a new vehicle...");
    vDriver.driveVehicle();
    vDriver.cleanVehicle();
  }
}

И вывод для этого будет:

1
2
3
4
5
6
Handling a new vehicle...
Driving a car...
Cleaning a car...
Handling a new vehicle...
Driving a Bus...
Cleaning a Bus...

Мы просто предоставили метод handleVehicle a Vehicle для обработки и не беспокоились о том, как он обрабатывается или кто его обрабатывает. Но в Java 7 и до реализации мы должны были знать, что существует некоторый абстрактный класс VehicleDriver а затем мы должны были переопределить его некоторый метод и затем создать экземпляр этого расширенного класса. Мое главное намерение, демонстрируя этот пример, состоит в том, чтобы использовать возможности Java 8 для создания более понятных и простых в использовании API. Но со всеми новыми функциями приходит обучение.

Примечание. В обеих приведенных выше реализациях общей частью являются классы Vehicle , Car , Bus которые используются в реализациях Java 7 и Java 8.

Ссылка: шаблон фабричного метода на Java от нашего партнера JCG Мохамеда Санауллы в блоге Experiences Unlimited .