В моем предыдущем посте о шаблонном шаблонном методе я показал, как можно использовать лямбда-выражения и методы по умолчанию . В этой статье я расскажу о шаблоне фабричного метода и узнаю, как можно использовать ссылки на методы, еще одну функцию, добавленную в 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 | interfaceVehicle{  publicvoiddrive();  publicvoidclean();}classCar implementsVehicle{  @Override  publicvoiddrive(){    System.out.println("Driving a car...");  }  @Override  publicvoidclean(){    System.out.println("Cleaning a car...");  }}classBus implementsVehicle{  @Override  publicvoiddrive(){    System.out.println("Driving a Bus...");  }  @Override  publicvoidclean(){    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 | abstractclassVehicleDriver{  publicabstractVehicle getVehicle();  publicvoiddriveVehicle(){    getVehicle().drive();  }  publicvoidcleanVehicle(){    getVehicle().clean();  }}classCarDriver extendsVehicleDriver{  @Override  publicVehicle getVehicle(){    returnnewCar();  }}classBusDriver extendsVehicleDriver{  @Override  publicVehicle getVehicle(){    returnnewBus();  }} | 
  В приведенной выше реализации 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 | publicclassFactoryMethodPattern {   publicstaticvoidmain(String[] args) {    handleVehicle(newCarDriver());    handleVehicle(newBusDriver());  }  staticvoidhandleVehicle(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 | interfaceVehicleDriver{    publicVehicle getVehicle();    publicdefaultvoiddriveVehicle(){        getVehicle().drive();    }    publicdefaultvoidcleanVehicle(){        getVehicle().clean();    }   } | 
  Теперь давайте перейдем к интересной части — Использование ссылок на VehicleDriver вместо создания другой реализации VehicleDriver .  Эти ссылки на метод обеспечивают способ для кода получить требуемый экземпляр класса Car или Bus без необходимости getVehicle() метод getVehicle() .  Смущенный?  Любопытно?  Давайте посмотрим, как мы можем достичь этого: 
| 01 02 03 04 05 06 07 08 09 10 11 12 | publicclassFactoryMethodPatternLambda {  publicstaticvoidmain(String[] args) {    handleVehicle(Car::new);    handleVehicle(Bus::new);  }  staticvoidhandleVehicle(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.