“Патерн Вівторка” #21: Фасад (Facade)

Уявімо, що ви вирішили провести свої вихідні дуже активно, а тому приїхали на зимовий курорт покататися на лижах. Перед тим як кататися вам добре б було пересвідчитися, що ввечері буде де заночувати і заплатити за проживання, тому ви йдете в місцевий готель і замовляєте собі кімнату у відповідності до ваших вимог. Потім звичайно що треба мати на чому кататися, тому ви йдете взяти лижі на прокат. Для того, щоб підібрати їх вас питаються вашу вагу, і рівень професіоналізму, потім ви підбираєте черевики і палки, для чого вас ще спитають ваш ріст і розмір взуття. Із цим усім на хребті ви йдете до каси і купляєте aбонемент на день. Не знаю як вас, але мене таке ходіння б дістало. Я б хотів якийсь термінал, де вводиш потрібні дані, оплачуєш і тобі зразу мужик видає черевики, лижі, палки, абонемент на день і ключі до номеру в готелі (і дівчину у номер o_O)*, або якщо мені хватає абонементу на день а лижне спорядження я маю, то я купляю абонемент на місці.

ФАСАД

Фасад – це дизайн патерн, що надає єдину “точку доступу” до підсистеми, тим самим спрощуючи її використання та розуміння.

В нашому прикладі фасадом буде термінал-обслуговувальна станція (SkiResortFacade) а підсистемою є ціла купа прокатних будок, кас, і готельних комплексів. Звичайно ми можемо полазити по курорту, якщо вам це подобається, але якщо дивитися із точки зору розробки програмного забезпечення, то якщо кожен собі буде лазити куди хоче і як хоче, то до добра таке не приведе, а лижники-новачки ніколи не будуть знати куди їм йти спочатку.

internal class SkiRent
{
public int RentBoots(int feetSize, int skierLevel)
{
return 20;
}
public int RentSki(int weight, int skierLevel)
{
return 40;
}
public int RentPole(int height)
{
return 5;
}
}

internal class SkiResortTicketSystem
{
public int BuyOneDayTicket()
{
return 120;
}
public int BuyHalfDayTicket()
{
return 60;
}
}

internal class HotelBookingSystem
{
public int BookRoom(int roomQuality)
{
switch (roomQuality)
{
case 3:
return 250;
case 4:
return 500;
case 5:
return 900;
default:
throw new ArgumentException("roomQuality should be in range [3;5]", "roomQuality");
}
}
}

public class SkiResortFacade
{
private SkiRent _skiRent = new SkiRent();
private SkiResortTicketSystem _skiResortTicketSystem = new SkiResortTicketSystem();
private HotelBookingSystem _hotelBookingSystem = new HotelBookingSystem();

public int HaveGoodOneDayRest(int height, int weight, int feetSize, int skierLevel, int roomQuality)
{
int skiPrice = _skiRent.RentSki(weight, skierLevel);
int skiBootsPrice = _skiRent.RentBoots(feetSize, skierLevel);
int polePrice = _skiRent.RentPole(height);
int oneDayTicketPrice = _skiResortTicketSystem.BuyOneDayTicket();
int hotelPrice = _hotelBookingSystem.BookRoom(roomQuality);

return skiPrice + skiBootsPrice + polePrice + oneDayTicketPrice + hotelPrice;
}

public int HaveRestWithOwnSkis()
{
int oneDayTicketPrice = _skiResortTicketSystem.BuyOneDayTicket();
return oneDayTicketPrice;
}
}

public class FacadeDemo
{
public static void Run()
{
var skiResortFacade = new SkiResortFacade();

int weekendRestPrice = skiResortFacade.HaveGoodOneDayRest(175, 60, 42, 2, 3);

Console.WriteLine("Price: {0}", weekendRestPrice);
}
}

Цей дизайн патерн можна розглядати як наступний рівень такого важливого принципу як інкапсуляція. Просто на цьому рівні ми інкапсулюємо цілу підсистему. Великі системи зазвичай здійснюють взаємозв’язок одна із одною за допомогою цього патерну. Космічна станція у космосі стикається із іншою за допомогою одного механізму, а не прикрученні сотні дротів поокремо. Також добрим тоном буде, якщо кожна із збірок які ви пишете має свого роду фасад, щоб її потім можна було легко використовувати із інших частин програми.

Дякую.

* добавив мій друг, після прочитання

Моя табличка Патернів
Developer's RoadMap To Success

2 коментарі

Add a Comment

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *