Фасад (шаблон проєктування)
Фаса́д — шаблон проєктування, призначений для об'єднання групи підсистем під один уніфікований інтерфейс, надаючи доступ до них через одну точку входу. Це дозволяє спростити роботу з підсистемами.
Фасад належить до структурних шаблонів проєктування.
Складові шаблону[ред. | ред. код]
Класи, з яких складається шаблон можна розділити на 3 частини:
- фасад;
- підсистеми;
- клієнти.
Ролі складових[ред. | ред. код]
Фасад[ред. | ред. код]
- Визначає певним підсистемам інтерфейс, отже знає кому адресувати запити;
- делегує запити клієнтів потрібним об'єктам підсистеми;
- створює нові методи, котрі об'єднують виклики об'єктів системи і\або додають свою логіку;
- приховує підсистеми;
- зменшує кількість параметрів методів, шляхом попередньої підстановки визначених значень.
Підсистема[ред. | ред. код]
- реалізує функціонал, закритий та не видимий для зовнішніх компонентів
- виконує роботу, запитану клієнтом через фасад.
- не зберігає посилання на фасад — це означає що одна підсистема може мати довільну кількість фасадів.
Клієнт[ред. | ред. код]
- здійснює запити фасаду;
- не знає про існування підсистем.
Переваги та недоліки[ред. | ред. код]
Переваги[ред. | ред. код]
- Приховує реалізацію підсистеми від клієнтів, що полегшує використання підсистеми
- Сприяє слабкій взаємодії між підсистемою та її клієнтами. Це дозволяє змінити класи, які включають підсистему, не впливаючи на клієнтів.
- Зменшує компіляційні залежностей у великих програмних системах
- Спрощує системи перенесення на інші платформи, оскільки менш імовірно, що для побудови однієї підсистеми потрібно побудувати всі інші
Недоліки[ред. | ред. код]
- Не заважає сучасним клієнтам отримувати доступ до базових класів
- Фасад не додає жодної функції, він просто спрощує інтерфейси
Випадки використання[ред. | ред. код]
Фасад використовується у випадках, коли потрібно:
- спростити доступ до складної системи;
- створити рівні доступу до системи;
- додати стійкість до змін підсистем;
- зменшити кількість сильних зв'язків між клієнтом та підсистемою, але залишити доступ до повної функціональності.
Зв'язок з іншими патернами[ред. | ред. код]
- Фасад створює новий інтерфейс доступу, адаптер — використовує старий
Реалізація[ред. | ред. код]
C++[ред. | ред. код]
#include <iostream> #include <string> using namespace std; // Абстрактний музикант - не є обов'язковою частиною патерну, введений для спрощення коду class Musician { private: string name; public: Musician(string name) { this->name = name; } virtual ~Musician() {} protected: void output(string text) { cout << this->name << " " << text << "." << endl; } }; // Конкретні музиканти struct Vocalist : public Musician { Vocalist(string name) : Musician(name) {} void singCouplet(string coupletNumber) { string text = "заспівав куплет №" + coupletNumber; output(text); } void singChorus() { output("заспівав приспів"); } }; struct Guitarist : public Musician { Guitarist(string name) : Musician(name) {} void playCoolOpening() { output("починає з крутого виступу"); } void playCoolRiffs() { output("грає круті рифи"); } void playAnotherCoolRiffs() { output("грає інші круті рифи"); } void playIncrediblyCoolSolo() { output("лабає неймовірно круте соло"); } void playFinalAccord() { output("закінчує пісню супер акордом"); } }; struct Bassist : public Musician { Bassist(string name) : Musician(name) {} void followTheDrums() { output("слідкує за барабанами"); } void changeRhythm(string type) { string text = "перейшов на ритм "; output(text + type); } void stopPlaying() { output("закінчує грати"); } }; struct Drummer : public Musician { Drummer(string name) : Musician(name) {} void startPlaying() { output("починає грати"); } void stopPlaying() { output("закінчує грати"); } }; // Фасад — в цьому випадку, рок-група class BlackSabbath { private: Vocalist* vocalist; Guitarist* guitarist; Bassist* bassist; Drummer* drummer; public: BlackSabbath() { vocalist = new Vocalist("Оззі Осборн"); guitarist = new Guitarist("Тоні Айоммі"); bassist = new Bassist("Гізер Батлер"); drummer = new Drummer("Біл Уорд"); } void playCoolSong() { guitarist->playCoolOpening(); drummer->startPlaying(); bassist->followTheDrums(); guitarist->playCoolRiffs(); vocalist->singCouplet("1"); bassist->changeRhythm("приспів"); guitarist->playAnotherCoolRiffs(); vocalist->singChorus(); bassist->changeRhythm("куплет"); guitarist->playCoolRiffs(); vocalist->singCouplet("2"); bassist->changeRhythm("приспів"); guitarist->playAnotherCoolRiffs(); vocalist->singChorus(); bassist->changeRhythm("куплет"); guitarist->playIncrediblyCoolSolo(); guitarist->playCoolRiffs(); } }; void main() { BlackSabbath* band = new BlackSabbath(); band->playCoolSong(); }
C#[ред. | ред. код]
using System; namespace FacadeExample { // Клас клієнта class Client { static void Main(string[] args) { //Створюємо екземпляр фасаду - інтерфейс підсистем Facade facade = new Facade(); facade.CallPaired(); Console.WriteLine("\n\n"); facade.CallUnpaired(); Console.ReadKey(); } } // Клас фасаду class Facade { Subsystem1 first; Subsystem2 second; Subsystem3 third; Subsystem4 fourth; Subsystem5 fifth; public Facade() { this.first = new Subsystem1(); this.second = new Subsystem2(); this.third = new Subsystem3(); this.fourth = new Subsystem4(); this.fifth = new Subsystem5(); } //Виклик методів з підсистем Subsystem2 та Subsystem4 public void CallPaired() { Console.WriteLine("Результати роботи методів підсистем з парним індексом (2,4)\n"); second.Method(); fourth.Method(); } //Виклик методів з підсистем Subsystem1, Subsystem3 та Subsystem5 public void CallUnpaired() { Console.WriteLine("Результати роботи методів підсистем з непарним індексом (1,3,5)\n"); first.Method(); third.Method(); fifth.Method(); } } // Клас підсистеми class Subsystem1 { public void Method() { Console.WriteLine("Метод першої підсистеми"); } } // Клас підсистеми class Subsystem2 { public void Method() { Console.WriteLine("Метод другої підсистеми"); } } // Клас підсистеми class Subsystem3 { public void Method() { Console.WriteLine("Метод третьої підсистеми"); } } // Клас підсистеми class Subsystem4 { public void Method() { Console.WriteLine("Метод четвертої підсистеми"); } } // Клас підсистеми class Subsystem5 { public void Method() { Console.WriteLine("Метод п'ятої підсистеми"); } } }
Джерела[ред. | ред. код]
- www.dofactory.com [Архівовано 29 квітня 2012 у Wayback Machine.]
- Design Patterns: Elements of Reusable Object-Oriented Software [Архівовано 9 листопада 2012 у Wayback Machine.]