Читати книгу - "Занурення в патерни проектування, Олександр Швець"
Шрифт:
Інтервал:
Додати в закладку:
Виконавши все це ви, імовірніше за все, не отримаєте миттєвої вигоди. Проте в майбутньому ви зможете використовувати альтернативні реалізації класів, не змінюючи код, що їх використовує.
ПрикладРозгляньмо ще один приклад, де робота на рівні інтерфейсу виявляється кращою, ніж прив’язка до конкретних класів. Уявіть, що ви робите симулятор софтверної компанії. У вас є різні класи працівників, які виконують ту чи іншу роботу всередині компанії.
ДО: класи жорстко пов’язані.
Спочатку клас компанії жорстко прив’язаний до конкретних класів працівників. Попри те, що кожен тип працівників виконує різну роботу, ми можемо звести їхні методи роботи до одного виду, виділивши для всіх класів загальний інтерфейс.
Зробивши це, ми зможемо застосувати поліморфізм у класі компанії, трактуючи всіх працівників однаково через інтерфейс Employee.
КРАЩЕ: поліморфізм допоміг спростити код, але основний код компанії все ще залежить від конкретних класів співробітників.
Тим не менше, клас компанії все ще залишається жорстко прив’язаним до конкретних класів працівників. Це не дуже добре, особливо, якщо припустити, що нам знадобиться реалізувати кілька видів компаній. Усі ці компанії відрізнятимуться конкретними працівниками, які їм потрібні.
Ми можемо зробити метод отримання працівників у базовому класі компанії абстрактним. Конкретні компанії повинні самі подбати про створення об’єктів співробітників. Отже, кожен тип компаній зможе мати власний набір співробітників.
ПІСЛЯ: основний код класу компанії став незалежним від класів співробітників. Конкретних співробітників створюють конкретні класи компаній.
Після цієї зміни код класу компанії став остаточно незалежним від конкретних класів. Тепер ми можемо додавати до програми нові види працівників і компаній, не вносячи зміни до основного коду базового класу компаній.
До речі, ви тільки що побачили приклад одного з патернів, а саме — Фабричного методу. Надалі ми ще повернемося до нього.
Віддавайте перевагу композиції перед спадкуваннямСпадкування — це найпростіший та найшвидший спосіб повторного використання коду між класами. У вас є два класи з кодом, який дублюється. Створіть для них загальний базовий клас та перенесіть до нього спільну поведінку. Що може бути простішим?
Але у спадкування є і проблеми, які стають очевидними лише тоді, коли програма обросла класами, і змінити ситуацію вже досить важко. Ось деякі з можливих проблем зі спадкуванням.
Підклас не може відмовитися від інтерфейсу або реалізації свого батька. Ви повинні будете реалізувати всі абстрактні методи батька, навіть якщо вони не потрібні для конкретного підкласу.
Перевизначаючи методи батька, ви повинні піклуватися про те, щоб не зламати базову поведінку суперкласу. Це важливо, адже підклас може бути використаний у будь-якому коді, що працює з суперкласом.
Спадкування порушує інкапсуляцію суперкласу, оскільки підкласам доступні деталі батька. Суперкласи можуть самі стати залежними від підкласів, наприклад, якщо програміст винесе до суперкласу які-небудь загальні деталі підкласів, щоб полегшити подальше спадкування.
Підкласи дуже тісно пов’язані з батьківським класом. Будь-яка зміна в батькові може зламати поведінку в підкласах.
Повторне використання коду через наслідування може призвести до розростання ієрархії класів.
У наслідування є альтернатива, яка називається композицією. Якщо спадкування можна виразити словом «є» (автомобіль є транспортом), то композицію — словом «містить» (автомобіль містить двигун).
Цей принцип поширюється і на агрегацію — більш вільний вид композиції, коли два об’єкти є рівноправними, і жоден з них не керує життєвим циклом іншого. Оцініть різницю: автомобіль містить і водія, але той може вийти й пересісти до іншого автомобіля або взагалі піти пішки самостійно.
ПрикладПрипустімо, вам потрібно змоделювати модельний ряд автовиробника. У вас є легкові автомобілі та вантажівки. Причому вони бувають з електричним двигуном та з двигуном на бензині. До того ж вони відрізняються режимами навігації — є моделі з ручним керуванням та автопілотом.
СПАДКУВАННЯ: розвиток класів у кількох площинах (тип вантажу × тип двигуна × тип навігації) призводить до комбінаторного вибуху.
Як бачите, кожен такий параметр призводить до збільшення кількості класів. Крім того, виникає проблема дублювання коду, тому що підкласи не можуть успадковувати декількох батьків одночасно.
Вирішити проблему можна за допомогою композиції. Замість того, щоб об’єкти самі реалізовували ту чи іншу поведінку, вони можуть делегувати її іншим об’єктам.
Композиція дає вам ще й іншу перевагу. Тепер, наприклад, ви можете замінити тип двигуна автомобіля безпосередньо під час виконання програми, підставивши в об’єкт транспорту інший об’єкт двигуна.
КОМПОЗИЦІЯ: різні види функціональності виділені у власні ієрархії класів.
Така структура властива патерну Стратегія, про який ми теж поговоримо у цій книзі.
Розглянемо ще п’ять принципів проектування, які відомі як SOLID. Вперше ці принципи були описані Робертом Мартіном у книзі Agile Software Development, Principles, Patterns, and Practices 6.
Досягти такої лаконічності у назві вдалося шляхом використання невеличких хитрощів. Справа в тому, що термін SOLID — це абревіатура, за кожною буквою якої стоїть окремий принцип проектування.
Головна мета цих принципів — підвищити гнучкість вашої архітектури, зменшити пов’язаність між її компонентами та полегшити повторне використання коду.
Але, як і все в цьому житті, дотримання цих принципів має свою ціну. Тут це, зазвичай, виражається
Увага!
Сайт зберігає кукі вашого браузера. Ви зможете в будь-який момент зробити закладку та продовжити читання книги «Занурення в патерни проектування, Олександр Швець», після закриття браузера.