Паттерн Фасад — структурный шаблон проектирования, позволяющий скрыть сложность системы путем сведения всех возможных внешних вызовов к одному объекту, делегирующему их соответствующим объектам системы. Несмотря на мудреное определение, наверное, самый простой шаблон проектирования и очень скоро вы в этом сами сможете убедиться.
Реализация: давайте попробуем разработать навигационную систему автомобиля. Перед поездкой водитель будет включать GPS, загружать данные о пробках, прокладывать путь и выключать после поездки. За каждое описанное действие будет отвечать отдельный класс, кроме включения и выключения. И так, класс управления электропитанием GPSPower:
1 2 3 4 5 6 7 8 9 10 |
class GPSPower{ public void powerOn(){ System.out.println("Power ON"); } public void powerOff(){ System.out.println("Power OFF"); } } |
Класс содержит два метода, один включает GPS другой выключает.
Следующий наш класс будет отвечать за получение информации о пробках на дорогах GPSNotifier:
1 2 3 4 5 6 7 |
class GPSNotifier{ public void downloadRoadInfo(){ System.out.println("Downloading road information..."); System.out.println("Download complete!"); } } |
Осталось только обработать полученную информацию о ситуации на дорогах и проложить оптимальный маршрут, этим будет заниматься класс RoadAdvisor:
1 2 3 4 5 |
class RoadAdvisor{ public void route(){ System.out.println("Create a route"); } } |
Настал волнующий момент посмотреть, как это все работает:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Example{ public static void main(String... args){ GPSPower power = new GPSPower(); GPSNotifier notifier = new GPSNotifier(); RoadAdvisor advisor = new RoadAdvisor(); //Водитель включает навигационную систему power.powerOn(); //Водитель нажимает кнопку загрузки информации о дорогах notifier.downloadRoadInfo(); //Водитель нажимает кнопку прокладки маршрута advisor.route(); //Водитель выключает навигационную систему power.powerOff(); } } |
Вывод:
Power ON
Downloading road information…
Download complete!
Create a route
Power OFF
Работает неплохо, но как вы можете заметить водитель приходится слишком много взаимодействовать с навигационной системой, если мы ничего не предпримем конкуренты нас смогут обойти. В этом нам и поможет паттерн Фасад, в качестве фасада, у нас будет выступать класс GPSInterface, который будет за водителя выполнять однотипные действия:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class GPSInterface{ private GPSPower power; private GPSNotifier notifier; private RoadAdvisor advisor; public GPSInterface(GPSPower power, GPSNotifier notifier, RoadAdvisor advisor){ this.power = power; this.notifier = notifier; this.advisor = advisor; } public void activate(){ power.powerOn(); notifier.downloadRoadInfo(); advisor.route(); } } |
В конструктор класса передаются все элементы, управление которыми мы хотим скрыть «за фасадом». Метод activate() будет выполнять всю рутинную работу за водителя – включать систему, загружать информацию о ситуации на дорогах и прокладывать оптимальный маршрут и это все по нажатию одной кнопки! Давайте проверим как работает наш новый класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
public class Example{ public static void main(String... args){ GPSPower power = new GPSPower(); GPSNotifier notifier = new GPSNotifier(); RoadAdvisor advisor = new RoadAdvisor(); GPSInterface gps = new GPSInterface(power, notifier, advisor); //Водитель включает навигационную систему gps.activate(); //Водитель выключает навигационную систему power.powerOff(); } } |
Вывод:
Power ON
Downloading road information…
Download complete!
Create a route
Power OFF
Я надеюсь вы обратили внимание, что отключение навигационной системы в нашем примере осталось низменным:
1 |
power.powerOff(); |
Это одна из полезных особенностей данного паттерна – мы вольны работать с классами, которые скрыты интерфейсом (фасадом), напрямую, если в этом есть необходимость. И так, если вам необходимо упростить работу с каким-либо интерфейсом или изолировать клиента от сложной системы, то паттерн Фасад будет идеальным выбором.
Паттерн Фасад полный код примера:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
package example; class GPSPower{ public void powerOn(){ System.out.println("Power ON"); } public void powerOff(){ System.out.println("Power OFF"); } } class GPSNotifier{ public void downloadRoadInfo(){ System.out.println("Downloading road information..."); System.out.println("Download complete!"); } } class RoadAdvisor{ public void route(){ System.out.println("Create a route"); } } class GPSInterface{ private GPSPower power; private GPSNotifier notifier; private RoadAdvisor advisor; public GPSInterface(GPSPower power, GPSNotifier notifier, RoadAdvisor advisor){ this.power = power; this.notifier = notifier; this.advisor = advisor; } public void activate(){ power.powerOn(); notifier.downloadRoadInfo(); advisor.route(); } } public class Example{ public static void main(String... args){ GPSPower power = new GPSPower(); GPSNotifier notifier = new GPSNotifier(); RoadAdvisor advisor = new RoadAdvisor(); GPSInterface gps = new GPSInterface(power, notifier, advisor); //Водитель включает навигационную систему gps.activate();; //Водитель выключает навигационную систему power.powerOff(); } } |