В моем предыдущем посте о шаблонном шаблонном методе я показал, как можно использовать лямбда-выражения и методы по умолчанию . В этой статье я расскажу о шаблоне фабричного метода и узнаю, как можно использовать ссылки на методы, еще одну функцию, добавленную в 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 wayDriving a car...Cleaning a car...Handling a new vehicle. Pre lambda wayDriving 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.