You are on page 1of 56

Урок №2

Структурні
патерни

Зміст
1. Поняття структурного патерну. . . . . . . . . . . . . . . . . . 5
2. Патерн Adapter. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.2. Причина виникнення патерну. . . . . . . . . . . . . . . . 7
2.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.4. Результати використання патерну . . . . . . . . . . . 11
2.5. Практичний приклад використання патерну. . 12
3. Патерн Bridge . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
3.2. Причини виникнення патерну. . . . . . . . . . . . . . . 15
3.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.4. Результати використання патерну . . . . . . . . . . . 17
3.5. Практичний приклад використання патерну. . . 18

2
Зміст

4. Патерн Composite . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4.2. Причини виникнення патерну. . . . . . . . . . . . . . . 20
4.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 21
4.4. Результати використання патерну . . . . . . . . . . . 22
4.5. Практичний приклад використання патерну . . . . 23
5. Патерн Decorator. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
5.2. Причини виникнення патерну. . . . . . . . . . . . . . . 26
5.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 27
5.4. Результати використання патерну . . . . . . . . . . . 29
5.5. Практичний приклад використання патерну. . 29
6. Патерн Facade. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
6.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
6.2. Причини виникнення патерну. . . . . . . . . . . . . . . 35
6.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 36
6.4. Результати використання патерну . . . . . . . . . . . 38
6.5. Практичний приклад. . . . . . . . . . . . . . . . . . . . . . . 38
7. Патерн Flyweight . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
7.2. Причини виникнення патерну. . . . . . . . . . . . . . . 40
7.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 41
7.4. Результати використання патерну . . . . . . . . . . . 43
7.5. Практичний приклад. . . . . . . . . . . . . . . . . . . . . . . 44

3
Компьютерная Академия ШАГ

8. Патерн Proxy. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
8.1. Мета патерну. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
8.2. Причини виникнення патерну. . . . . . . . . . . . . . . 47
8.3. Структура патерну . . . . . . . . . . . . . . . . . . . . . . . . . 48
8.4. Результати використання патерну . . . . . . . . . . . 49
8.5. Практичний приклад. . . . . . . . . . . . . . . . . . . . . . . 50
9. Аналіз і порівняння структурних патернів . . . . . . 52
10. Домашнє завдання . . . . . . . . . . . . . . . . . . . . . . . . . . . 55

Додаткові матеріали уроку прикріплені до даного PDF-файлу.


Для доступу до матеріалів, урок необхідно відкрити в програмі
Adobe Acrobat Reader.

4
1. Поняття структурного патерну

1. Поняття структурного
патерну
Основуючись на визначенні інформаційних систем,
очевидним є те, що будь-яке програмне рішення, так чи
інакше, оперує деякою сукупністю даних, при аналізі
яких ми отримуємо деяку інформацію, завдяки якій ми
здійснюємо бізнес рішення і штатні рішення з управлін-
ня інформаційною системою.
Аналіз даних передбачає, що вони мають бути струк-
турованими. Це дозволить, з одного боку, ідентифікува-
ти різні дані (логічно відрізняти їх між собою), а з іншо-
го — організовувати атомарні величини у структуровані
об'єкти і їх сукупності. Структурування даних необхідне
для відображення понять, якими ми оперуємо під час
аналізу, і навіть відображення зв'язків, які утворюються
між об'єктами у процесі їх появи.
Об'єктно-орієнтований підхід надає нам багатий ін-
струментарій у сенсі опису структурованих понять та
відображення відносин, у яких вони складаються. Про-
те організація структури, що пов'язує поняття у працю-
ючу систему, має вирішальне значення з погляду ефек-
тивного застосування інформаційної системи, також як
і з погляду супроводу отриманого в результаті процесу
розробки продукту.
Патерни проєктування, у загальному сенсі, відобра-
жають найкращі моделі вирішення прикладних проблем,

5
Урок №2

що пройшли перевірку часом та практикою застосування.


Структурні патерни пропонують моделі організації даних
у структури, які найкращим чином вирішують питання
щодо організації управління даними, які ми використо-
вуємо у прикладних рішеннях. Слід розуміти, що даними
можна вважати як атомарні величини, так і усі об'єкти,
які є у межах нашого додатку.
Далі буде перелік основних структурних патернів, ви-
знаних світовим співтовариством як кращою практикою
у розробці програмного забезпечення.

6
2. Патерн Adapter

2. Патерн Adapter

2.1. Мета патерну


Для кращого розуміння даного матеріалу, а також з ме-
тою спрощення викладу, ми будемо використовувати таку
спеціальну термінологію, притаманну розглянутому питан-
ню: під «клієнтом» (client) ми розумітимемо деякий клас,
який використовує (загалом агрегує) деякий клас, який
ми називаємо адаптованим (adaptee). Під «адаптером»
(adapter) ми розумітимемо клас, який приводить інтерфейс
адаптованого класу до інтерфейсу, очікуваного клієнтом.
Мета патерну проєктування Adapter (від англ. «адап-
тер») полягає в тому, щоб привести (адаптувати) інтер-
фейс певного адаптованого класу до інтерфейсу, який
очікується клієнтом.

2.2. Причина виникнення патерну


Досить часто зустрічається наступна проблема: у
наборі інструментів у нас є певний клас, який ми вико-
ристовуємо у неспецифічній задачі для його структури.
Наприклад, у нас оголошено тип даних, що описує понят-
тя мережного пристрою, який ми називаємо IPEndPoint,
і наділений такими властивостями як IP-адреса, мак-
адреса та ім’я хосту, які ми використовуємо з метою пев-
ного прикладного аналізу (наприклад, трасування пере-
міщення пакетів). Аналіз виконується певним класом,
який агрегує безліч об'єктів типу IPEndPoint і називається

7
Урок №2

NetView. Однак, ми хочемо реалізувати графічне уявлення


для процесу та результату аналізу, з виведенням його на
основне вікно нашої програми. Проблема полягає в тому,
що клас NetView немає інтерфейсу, специфічного об'єкта
графічної підсистеми і, відповідно, не може бути вико-
ристаний віконним класом для виконання промальову-
вання. Ми не маємо можливості «переписати» (змінити
початковий текст і, відповідно, структуру) клас NetView
під потреби додатка, оскільки він є частиною використо-
вуваного нами набору типів з dll-бібліотеки, наданої сто-
ронніми розробниками; або ми просто не хочемо «пере-
вантажувати» структуру класу, оскільки вона критична
для будь-яких завдань нашого додатка.
У такому разі логічно використати певний клас-по-
середник, який, використовуючи наслідування, дозво-
лить навести клас NetView до необхідного типу даних,
а також за допомогою перевизначення методів, специ-
фічних для компонента графічної підсистеми, визна-
чить інтерфейс промальовування типу даних NetView.
Такий клас-посередник, зазвичай, називають адап-
тером.

2.3. Структура патерну


Структура патерну Adapter представлена на наведе-
ній діаграмі (рис. 1).
Елементи, які беруть участь:
■ Client — клас, який використовує деякі допоміжні типи
даних і очікує, що вони мають стандартний інтерфейс
взаємодії (використання), описаний класом Target.

8
2. Патерн Adapter

Рисунок 1

■ Target — клас, що має інтерфейс, очікуваний клієнтом.


■ Adaptee — клас, необхідний для роботи клієнта, але
має інтерфейс, відмінний від того, який очікується
клієнтом.
■ Adapter — клас, що виконує приведення інтерфейсу
класу Adaptee до інтерфейсу класу Target.
У запропонованій вище структурі, приведення ін-
терфейсу виконується за рахунок того, що клас Adapter
успадковує обидва класи Adaptee і Target, а значить, має
інтерфейси обох цих класів. Потім клас Adapter наво-
дить виклики методів специфічних для інтерфейсу кла-
су Target до викликів відповідних методів інтерфейсу
класу Apadtee.

9
Урок №2

На наведеній діаграмі (рис. 2) послідовності демон-


струється, що виклики методів об'єкта класу Adapter зво-
дяться до викликів методів об'єкта базового класу.

Client Target Adaptee Adapter

Request()

SpecificRequest()

<<return>>

<<return>>

Рисунок 2

Рисунок 3

10
2. Патерн Adapter

Патерн Adapter також може бути реалізований аль-


тернативним способом, структура якого представлена на
наведеній діаграмі (рис. 3).
Відміна від попередньої структури у тому, що у по-
точній моделі класи Adapter і Adaptee знаходяться не у
відношенні спорідненості, а у відношенні асоціації, тоб-
то клас Adapter агрегує клас Adaptee.
Таким чином, приведення інтерфейсу класу Adaptee
до інтерфейсу класу Target виконується за рахунок того,
що виклики методів об'єкта класу Adapter, специфічні для
інтерфейсу класу Target, наводяться до викликів відповід-
них методів об’єкта класу Adaptee, інкапсульованого у класі
Adapter. Діаграма послідовності, наведена нижче (рис. 4),
ілюструє те, що ми описали.

Client Target Adapter Adaptee

Request()
adaptterSpecificRequest()

<<return>>

<<return>>

Рисунок 4

2.4. Результати використання патерну


Основний позитивний результат використання па-
терну проєктування Adapter полягає в тому, що ми от-
римуємо можливість гнучко привести інтерфейс деякого

11
Урок №2

класу до інтерфейсу, що очікується додатком без зміни


структури самого класу. Це необхідно, як з погляду усу-
нення надмірності структури типів, і з погляду модуль-
ності створюваних додатків.
Надмірність відіграє негативну роль тоді, коли нам
необхідно повторно використовувати написаний нами
код (наприклад, в іншому додатку). Такий код назива-
ють «reusable-кодом». Створення reusable-коду вважа-
ється чудовою практикою, оскільки зменшує вартість та
збільшує швидкість розробки. Також збільшує гнучкість
і масштабованість створюваних додатків за рахунок мо-
дульної структури готового додатка.
Розширювати додаток шляхом додавання нових ти-
пів значно простіше, ніж повністю заново створювати
деякі модулі.

2.5. Практичний приклад використання патерну


Ми розглянемо використання патерну Adapter на
прикладі додатка, який керує товарообігом певного під-
приємства. Для керування товарами ми опишемо тип да-
них Product (продукт/товар), який буде організовано у
колекцію товарів за допомогою класу Products­Collection.
Наш додаток також керує й іншими аспектами ро-
боти торговельного підприємства, які ми «усунемо» для
прозорості прикладу. Далі представлена діаграма класів
(рис. 5), що ілюструє вище вказаний додаток.
Для реалізації можливості створювати резервну ко-
пію даних, що переноситься, яку можна використовува-
ти для практично будь-яких завдань, ми вирішили зро-

12
2. Патерн Adapter

бити так, щоб можна було всі дані експортувати в окремі


xml-файли. Для цього ми реалізували клас XmlIO, який
здійснює запис і читання Xml-документа, об’єкт якого
інкапсулюється віконним класом нашого додатку. Для
реалізації запису у файл колекції продуктів нами було
створено клас ProductXmlIOAdapter, який інкапсулює
колекцію продуктів, реалізує приведення цієї колекції
до xml-документу, а також xml-документа до колекції.

Рисунок 5
Таким чином, ми реалізуємо функцію запису колекції
елементів у файл в xml-форматі, і водночас не змінюємо

13
Урок №2

структури вихідного типу даних, та усуваємо надмірність


структури, яка могла з'явитися внаслідок наповнення кла-
су Product додатковим функціоналом. Усунення надмір-
ності необхідно настільки, наскільки тип даних Product
може використовуватися при приведенні інформації про
продукти, отриманої з деякої бази даних, до об'єктного
уявлення для виконання подальшого аналізу і т. д. При
виконанні усіх цих процесів, надмірність структури типу
може створювати додаткові складності. Також, подібна
модульна структура додає гнучкості при супроводі про-
єкту та використанні (створенні) reusable-коду.
В матеріалах до цього уроку є папка Samples, в якій ви
зможете знайти реалізацію патерну Adapter.

14
3. Патерн Bridge

3. Патерн Bridge
3.1. Мета патерну
Мета патерну Bridge (з англ. «міст») полягає в тому,
щоб відокремити абстракцію від її реалізації, щоб вони
могли змінюватися незалежно один від одного.
3.2. Причини виникнення патерну
Зазвичай, у випадках, коли деяка абстракція (зазви-
чай абстрактний клас) може мати декілька певних реа-
лізацій, використовують наслідування визначення мно-
жини класів зі схожим (загалом, говорять однаковим або
сумісним) інтерфейсом. Абстрактний клас визначає ін-
терфейс для своїх нащадків, який вони реалізують «різ-
ними» засобами.
Однак, такий підхід не завжди є досить гнучким і має
деякі слабкі сторони, здатні призвести до надмірності коду,
а також створити додаткові складнощі підчас ведення про-
єкту, що значно збільшить його вартість. Пряме успадку-
вання інтерфейсу абстракції певним класом пов'язує реа-
лізацію з абстракцією безпосередньо, що створює складно-
щі при подальшій модифікації реалізації (її розширення),
а також не дозволяє повторно використовувати абстрак-
цію і її реалізацію окремо одна від одної. Реалізація, нена-
че стає «жорстко пов'язаною» з абстракцією.
Патерн проєктування «міст» передбачає розташу-
вання інтерфейсу та його реалізації в різних ієрархіях,

15
Урок №2

що дозволяє відокремити інтерфейс від реалізації та ви-


користовувати їх незалежно, а також комбінувати будь-
які варіанти реалізації з різними уточненими варіанта-
ми абстракції.
3.3. Структура патерну
Патерн проєктування «міст» представлений такими
структурними елементами:
■ Abstraction (абстракція) — визначає інтерфейс абстрак-
ції, а також містить об'єкт виконавця, який визначає
інтерфейс реалізації.
■ Implementor (виконавець) — визначає інтерфейс для
класів реалізації. Інтерфейс виконавця не обов’язково
має відповідати інтерфейсу абстракції. Взагалі, інтер-
фейси, визначені абстракцією та виконавцем, можуть
бути абсолютно різними, що є досить гнучким. За-
галом, виконавець має визначати базові операції, на
яких згодом базується високорівнева логіка абстракції.
■ RefinedAbstraction (уточнена абстракція) — розширює
інтерфейс, визначений абстракцією.
■ ConcreteImplementor (конкретизований виконавець) —
клас, який реалізує інтерфейс виконавця і визначає
його приватну реалізацію.
Абстракція та виконавець спільно утворюють «міст»,
який пов'язує уточнену абстракцію з конкретною реалі-
зацією.
Структура патерна проєктування «міст» представле-
на нижче як діаграми класів (рис. 6).

16
3. Патерн Bridge

Рисунок 6

3.4. Результати використання патерну


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

17
Урок №2

3.5. Практичний приклад використання патерну


Ми розглянемо застосування патерну проєктуван-
ня «міст» на прикладі «змішаного» графічного редактора
(який дозволяє спільно, в рамках одного уявлення, реда-
гувати растрову та векторну графіку).
Модель додатка передбачає наявність деякого гра-
фічного уявлення, що оперує деякими абстрактними фі-
гурами, інтерфейс взаємодії з якими описується в інтер-
фейсі Figure, який відіграє роль абстракції в цьому при-
кладі (рис. 7).

Рисунок 7

18
3. Патерн Bridge

Інтерфейс виконавця визначається інтерфейсом Figure­


Imp, від якого ми наслідуємо класи VectorFigure і Raster­
Figure, які описують реалізації промальовування вектор-
ної та растрової фігури.
Після визначення реалізації ми можемо уточнити аб-
стракцію, описавши інтерфейс певної конкретної фігури
(наприклад, еліпса). Після цього можна пов'язати уточ-
нену абстракцію з конкретною реалізацією, наприклад,
визначивши класи VectorEllipse і RasterEllipse, які опису-
ють векторний та растровий еліпси.
В матеріалах до цього уроку є папка Samples, в якій
ви зможете знайти реалізацію патерну Bridge.

19
Урок №2

4. Патерн Composite
4.1. Мета патерну
Патерн Composite (компонувальник) призначений
для того, щоб уявити об'єкти у вигляді структури дерева
у ієрархічному зв'язку «частина-ціле».

4.2. Причини виникнення патерну


Патерн компонувальник існує тому, що структура
типу «дерево» є досить розповсюдженою і часто вико-
ристовується для організації даних, що мають регулярну
структуру. Тобто таку структуру, яка реалізує ієрархічну
залежність «частина-ціле», яка передбачає, що елементом
деякої композиції даних може бути не лише елементар-
ний елемент, але й така сама композиція.
Найпростіша реалізація подібної структури з ре-
курсивною системою вкладеності може бути виражена
у вигляді деякої системи типів з класами, що описують
елементарні компоненти, і класів, які використовувати-
муться як контейнери для елементарних компонентів.
Але подібний підхід має серйозний недолік — код, який
використовує вказані класи, повинен окремо обробляти
елементи та їх контейнери, навіть якщо вони обробля-
ються однаково. Це різко ускладнює реалізацію програми.
Патерн компонувальник пропонує рекурсивну струк-
туру, з якою не доведеться приймати рішення у тому, як
обробляти окремі елементи загальної сукупності даних.

20
4. Патерн Composite

Ключ до розуміння природи компонувальника по-


лягає у визначенні абстрактного ідентичного інтерфейсу
для елементарних компонентів та їх контейнерів. Таким
чином, оскільки контейнери та елементарні компонен-
ти знаходяться у зв'язку спорідненості і мають спільний
користувацький інтерфейс, то контейнер може бути еле-
ментом іншого такого ж контейнера, що створює зручну
регулярну (рекурсивну) структуру.
4.3. Структура патерну
■ Component (компонент) — визначає інтерфейс для
об'єктів та його композицій; реалізує базову поведінку,
специфічну й для окремих елементів і їх композицій;
визначає інтерфейс доступу до елементів композиції і
управління цими елементами, а також визначає інтер-
фейс доступу до батьківського елемента рекурсивної
структури.
■ Leaf (лист) — визначає окремий елемент композиції
та встановлює поведінку «примітивних» (базових)
елементів загальної структури.
■ Composition (композиція) — визначає поведінку для
компонентів, що містять дочірні елементи, інкапсулює
дочірні елементи, а також реалізує операції керування
дочірніми елементами та доступу до них, визначені
інтерфейсом компонента.
■ Client (клієнт) — керує елементами композиції через
інтерфейс компонента.
Структура патерна «компонувальник» представлена
діаграмою класів на рисунку 8

21
Урок №2

Рисунок 8

4.4. Результати використання патерну


Використання патерна «компонувальник» допомагає
спростити організацію елементів у вигляді вкладеної струк-
тури даних і усуває надмірність коду при реалізації цьо-
го завдання. Також компонувальник робить клієнтський
об'єкт більш простим і дозволяє йому обробляти елемен-
тарні компоненти та їх композиції однаково, через їх уні-
фікований інтерфейс, визначений класом-компонентом.

22
4. Патерн Composite

Компонувальник спрощує процес додавання нових


компонентів. Нові класи, незалежно від того, є вони еле-
ментарними компонентами або композиціями, працюва-
тимуть зі структурою, яка вже існує на момент їх створен-
ня. Інакше кажучи, немає необхідності змінювати клієнта
при створенні нових компонентів.

4.5. Практичний приклад використання патерну


Ми розглянемо застосування патерну проєктуван-
ня «компонувальник» на основі організації множини
елементів графічного інтерфейсу користувача, яке має
регулярну структуру. Інакше кажучи, будь-яке вікно
може містити елементи управління, але й інші вікна.
Вікна можна спрощено визначити як композиції еле-
ментів керування.
Для організації компонувальника під певне завдання
ми оголошуємо абстрактний клас UIElement, який опи-
сує деякий елемент графічного інтерфейсу користувача
та визначальний інтерфейс базової поведінки елемента
графічного інтерфейсу та інтерфейс керування дочірні-
ми елементами композиції.
До базової поведінки елемента графічного інтерфейсу
належать методи Hide, Paint і Show, які відповідно реалі-
зують можливість показувати елемент, перемальовувати
його графічне уявлення та ховати.
Для управління-доступу до дочірніх елементів ком-
позиції визначаються методи Add, GetChild і Remove, які
дозволяють додавати новий дочірній елемент, отримати
його та видалити елемент із композиції.

23
Урок №2

Модель описаного додатка представлена діаграмою


класів на рисунку 9.

Рисунок 9

Клас Control, визначає елемент управління, який ви-


ступає у ролі «примітивного» елемента, реалізованого

24
4. Патерн Composite

нами компонувальника та реалізує базову поведінку. Клас


Window є композицією елементів управління, але також
реалізує і базову поведінку, оскільки має деяке елемен-
тарне графічне уявлення.
Клас Application виступає у ролі клієнта, який асо-
ційований із деяким вікном, тобто використовує об'єкт
класу Window та інтерфейс, описаний класом UIElement.
В матеріалах до цього уроку є папка Samples, в якій
ви знайдете реалізацію патерну Composite.

25
Урок №2

5. Патерн Decorator
5.1. Мета патерну
Мета патерну Decorator (від англ. «декоратор») по-
лягає у тому, щоб реалізувати можливість динамічного
додавання функціоналу до об'єкта, а також розподілити
відповідальність за виконання окремих функцій між ок-
ремими класами.
Також декоратор є альтернативою наслідування у
сенсі розширення функціоналу об'єктів.

5.2. Причини виникнення патерну


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

26
5. Патерн Decorator

Декоратор дозволяє не тільки гнучко комбінувати


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

5.3. Структура патерну


Структура патерну Decorator представлена такими еле-
ментами (рис. 10):

ConcreteDecoratorA ConcreteDecoratoB ConcreteСomponent

Operation
Operation

<<return>>

AddedBehaviorB

<<return>>
AddedBehaviorA

Рисунок 10

■ Component — абстракція деякого елемента, для якого


будуть визначені «декорації» (оформлення). Звісно,

27
Урок №2

під «декоруванням» розуміється не візуальне оформ-


лення, а додавання спеціальних функцій. Component
містить оголошення абстрактної операції, до конкрет-
ної реалізації якої декоратор згодом додасть «новий»
функціонал.
■ ConcreteComponent — реалізація компонента.
■ Decorator — клас, який успадковує та агрегує ком-
понент. Він перевизначає реалізацію операції таким
чином, щоб виконати функцію, інкапсульовану в
компоненті, а потім додати новий функціонал.

Рисунок 11

Оскільки декоратор є окремим випадком компонен-


та (успадковує Component), то в якості інкапсульованого

28
5. Патерн Decorator

компонента може бути використаний інший декоратор,


що дозволяє здійснювати рекурсивну послідовність ви-
кликів перевизначеної операції з поступовим накопичен-
ням функціоналу (як показано на діаграмі послідовності).
ConcreteDecoratorA і ConcreteDecoratorB — являють
собою приватні реалізації декоратора для компонента.
Структура патерну проєктування декоратор (Deco­
ra­tor) ілюструється представленою на рисунку 11 діагра-
мою класів.
5.4. Результати використання патерну
Використання патерна, як вже згадувалося вище, доз-
воляє більш гнучко, ніж при використанні успадкуван-
ня, реалізувати розподіл обов'язків з виконання деякої
складної задачі між декількома класами.
З іншого боку патерн проєктування «декоратор» за-
побігає перенасичення ієрархії класів, оскільки дозволяє
уникати необхідності створювати класи, які поєднували
б у собі функціонал у всіх необхідних комбінаціях.

5.5. Практичний приклад використання патерну


Розглянемо на прикладі модель текстового редакто-
ра з відображенням html-синтаксису.
Передбачається використовувати клас текстового
представлення для реалізації логіки представлення тек-
стової інформації користувачеві. Модель реалізації тек-
стового уявлення наведена на рисунку 12.
Клас текстового уявлення (TextView) унаслідується,
з одного боку, класом конкретної реалізації уявлення у

29
Урок №2

вигляді текстової області (клас TextArea), що підтримує


редагування. Для підтримки можливості розширення
функціоналу текстового уявлення, ми оголошуємо клас
TextDecorator, який, власне, і реалізує патерн Decorator.

Рисунок 12

Для реалізації можливості відображення html-синтак-


сису, ми створимо певну реалізацію класу TextDecorator,
яка інкапсулює логіку здійснення відображення html-син-

30
5. Патерн Decorator

таксису у текстовому уявленні. При здійсненні прорисо-


вування вікна, в якому використовується текстове уяв-
лення (обробник події Paint), створюється зображення за
розміром клієнтської області програми, для якої ініціалі-
зується графічний контекст. Об’єкт графічного контексту
створеного зображення передається у метод Paint об'єкта
класу HtmlHighlightDecorator, який викликає метод Paint
об'єкта класу TextArea, а згодом і метод DrawColoredText,
відповідальний за прорисовування відображеного тек-
сту. Послідовність викликів наведена нижче на діаграмі
послідовності (рис. 13).

Window HtmlHighlightDecorator ConcreteСomponent

OnPaint

Paint(DC)

Paint(e)

<<return>>

DrawColoredText(e)

AddedBehaviorA

<<return>>

Рисунок 13

Таким чином, після повернення керування до оброб-


ника події Paint класу вікна, на створеному в обробни-

31
Урок №2

ку зображенні буде прорисовано текст із відображеним


синтаксисом. На останньому етапі ми прорисуємо отри-
мане зображення на графічному контексті вікна, з яким
пов'язане текстове уявлення. Подібна реалізація дозво-
лить згодом гнучко додавати та видаляти різні ефекти
дизайну, властиві текстовим редакторам. Наприклад, но-
мери рядків, що з'єднують лінії для парних елементів, як
показано на рисунку 13.

Рисунок 14

Для цього достатньо оголосити декілька декораторів


і додати їх для текстового уявлення у класі вікна, з яким
пов'язане текстове уявлення.
Узагальнена модель наведена на рисунку 15.
В матеріалах до цього уроку є папка Samples, в якій
ви знайдете реалізацію патерну Decorator.

32
5. Патерн Decorator

Рисунок 15

33
Урок №2

6. Патерн Facade

Патерн Facade (фасад) призначений, більшою мірою,


для інкапсуляції (приховування) вмісту і розподілу логіч-
них частин на незалежні підсистеми. На практиці під час
роботи над проєктами застосовується структура патерну
«фасад». Явний приклад цьому слугує будь-який ресто-
ран швидкого харчування, де ви замовляєте їжу на касі, а
подальша структура процесів діяльності забігайлівки вас
як клієнта, як правило, мало турбує. Але в забігайлівці
також є офіс, до якого ви теж можете прийти або зверну-
тися через інтерфейс (наприклад, стати постійним клієн-
том). Таким чином, ресторан отримує дві мінімально за-
лежні один від одного підсистеми, які разом складаються
в одну велику систему.

Користувач

«subsystem» «subsystem»
Ресторан Офіс

Каса Приймальна

Бухгалтерія
Кухня Відділ кадрів

Склад Робота з
Прибирання клієнтами Маркетинг
приміщень

Рисунок 16

34
6. Патерн Facade

6.1. Мета патерну


Метою патерну «фасад» є певна структуризація кла-
сів, в підсистеми, доступ до кожної з них відбувається че-
рез один інтерфейс. Так само й підчас побудови архітек-
тури додатка бажано його розділяти на окремі системи,
які мають бути максимально незалежними.
Кожна частина програми (підсистема) матиме свій
клас «фасад», через який проводитиметься керування
цією частиною програми.

6.2. Причини виникнення патерну


Спроєктувати і потім побудувати масивний додаток
«одразу» дуже складно. Архітектори вирішили це завдан-
ня розбиттям програми на дрібніші підсистеми, що доз-
воляє будувати якусь одну частину програми, не відволі-
каючись на інші її аспекти, а після побудови — переходи-
ти до написання наступної підсистеми. А якщо будувати
системи незалежними одна від одної, можна отримати
«безпечний» замінник її компонентів або цілих підсис-
тем. Також, отримуючи незалежну підсистему, ви змо-
жете використати її повторно в інших проєктах. І якщо
команда програмістів налічує більше одного розробни-
ка, це дозволить доручити кожному (або декільком) з них
написати окрему підсистему, а потім зібрати ці підсисте-
му у єдиний додаток.
Але для того щоб скористатися незнайомою вам під-
системою, доводилося перечитувати чимало документа-
ції про цю структуру і розбиратися, як нею користувати-
ся. Для вирішення цієї проблеми, був створений патерн

35
Урок №2

«Фасад» (Facade). Який передбачає, що для кожної під-


КОМПЬЮТЕРНАЯ АКАДЕМИЯ «ШАГ»
системи буде створений свій клас, який є певним збері-
гачем підсистеми. Через такий клас буде легко взаємоді- 26

яти зі структурою.

Структура паттерна Рисунок 17


Паттерн фасад подразумевает существование некоторой подсистемы в
6.3. Структура
программе, патерну
для которой создается класс фасад. Через класс фасада
инициируется выполнение операций из классов подсистемы.
Патерн «фасад» передбачає існування деякої підсис-
Стоит так же отметить то, что клиенты (пользователи подсистемы) не
теми в програмі, для якої створюється клас «фасад». Че-
должны иметь доступа к классам подсистемы.
рез клас фасаду ініціюється виконання операцій із кла-
Все объекты подсистемы, если это возможно должны храниться в классе
сів підсистеми.
фасад. При вызове клиентами метода из объекта Facade, он начинает работу с
классами подсистемы.
36
6. Патерн Facade

Варто зазначити, що клієнти (користувачі підсисте-


ми) не повинні мати доступу до класів підсистеми.
Всі об'єкти підсистеми, якщо це можливо, мають збе-
рігатися в класі «фасад». При виклику клієнтів методу з
об'єкту Facade, він починає роботу з класами підсистеми.

UserClass Facade Class Class Class

StartWork2()

Operation1()

Operation1()

Operation2()

Operation1()

<<return>>

Рисунок 18

Описаний вище приклад не є правилом. В патерні


«фасад» можуть бути близько трьох класів всередині під-
системи. Об'єкт класу «фасад» може не тільки виклика-
ти методи з елементів підсистеми, а й налаштовувати їх,
присвоювати їх значення властивостям тощо.
Необов'язково клас фасаду має зберігати об'єкти кла-
сів підсистеми.

37
Урок №2

Доступ до об'єктів підсистеми можна налаштувати


через патерн Proxy. Також іноді програмісти роблять клас
фасаду статичним, щоб до нього можна було звернутися
з будь-якої точки програми.

6.4. Результати використання патерну


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

6.5. Практичний приклад


Розглянемо патерн «фасад» на прикладі наступного
додатка: простий перекладач слів, користувач вводить
слово англійською і в результаті отримує його переклад
українською.
Додаток має надавати можливість працювати зі слов-
ником заздалегідь записаних слів (зберегти, завантажи-
ти) з файлу. Також додаток має вміти додавати нові слова
до текстової бази даних.

38
6. Патерн Facade

Програмою передбачена підсистема


КОМПЬЮТЕРНАЯ АКАДЕМИЯ «ШАГ» для роботи зі

словником, доступ до якої буде здійснено через об'єкт29


класу фасад.
Далі представлена діаграма класів цього додатку (рис. 19).

Рисунок 19
Пользователь будет управлять системой через класс фасад(FacadeFileBase)
Користувач керуватиме системою через клас «фасад»
который в свою очередь вызывает объекты подсистемы.
В(FacadeFileBase), який Samples.
папке урока есть папка у свою чергу
В ней викликає
вы можете об’єкти під-
найти реализацию
системи.
паттерна Facade.

В матеріалах до цього уроку є папка Samples, в якій


ви зможете знайти реалізацію патерну Facade.

39
Паттерны проектирования - Урок №2
Урок №2

7. Патерн Flyweight
7.1. Мета патерну
Метою патерну є більш економне використання пам'яті
комп'ютера. Досягається це більш правильним способом
роботи з великою кількістю дрібних об'єктів.
Для розуміння роботи патерна необхідно навчити-
ся розділяти внутрішні та зовнішні властивості об'єкта.
Внутрішня властивість об'єкта — це властивість, яка збе-
рігає об'єкт у собі. Тобто це екземпляр класу, всередині
якого створено властивість (змінна), і зберігається, доки
«живе» об'єкт. Зовнішня властивість — це властивість,
яка передається об'єкту як аргумент одного (або кількох)
методу, і існує, доки виконується метод.
Суть патерна полягає в тому, щоб «переписати» вну-
трішні властивості у зовнішні і потім не створювати бага-
то об'єктів, а створити один, який «відображатиметься»
по-різному, залежно від того, які зовнішні властивості
до нього будуть застосовані.

7.2. Причини виникнення патерну


Після «переходу» на ООП стало простіше програму-
вати, оскільки всі об'єкти виглядають «як справжні», але
це пов'язано з деякою кількістю труднощів. Створюючи
модель програми, хочеться розташувати об'єкти за прин-
ципами об'єктно-орієнтованого програмування, напри-
клад: стілець складається із ніжок та сидіння, а сидіння

40
7. Патерн Flyweight

складається ще з декількох деталей. Якщо описувати таку


архітектуру занадто «глибоко», може виникнути ситуація,
коли об'єктів буде занадто багато, від чого додаток з такою
архітектурою «гальмуватиме» процес. Що ж робити, коли
необхідний рівень «глибини» недосяжний для комп'юте-
ра? Відповідь: розділити логічне розуміння додатку від фі-
зичного, оскільки на відміну від реального життя в про-
грамуванні можна зустріти моменти, коли одна й та сама
сутність перебуває «рисується» у двох (або більше) міс-
цях. Так, наприклад за логікою, маємо стілець, який скла-
дається з ніжок та сидіння, а фізично у програмі створе-
но об'єкт ніжки, яка фігурує в різних місцях. Для того, аби
об'єкт фігурував у різних місцях, достатньо при виклику
метода з об'єкта «відобразити» передавати у нього деяку
кількість параметрів, які і будуть вказувати де і як відобра-
жати цей елемент. Використовуючи такий підхід до побу-
дови архітектури, програміст отримає додаток, який буде
досить економічно використовувати ресурси комп'ютера.

7.3. Структура патерну


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

41
Урок №2 КОМПЬЮТЕРНАЯ АКАДЕМИЯ «ШАГ»

тах їм має повертатися вже створений об'єкт, який, як було


зазначено вище, повинен зберігатися всередині фабрики.

Рисунок 20

42
Классы A,B,C наследуются от базового класса, который описы
интерфейс взаимодействия со всеми типами приспособленцев.
7. Патерн Flyweight

При виклику методу GetObj, користувач передає до


нього ідентифікатор об’єкта, який йому необхідно от-
римати. Якщо об’єкт з таким індексом вже створений,
його необхідно повернути як результат роботи методу.
Але якщо об’єкт не створено, його необхідно створити
і записати у сховище фабрики, після чого повернути як
його як результат роботи методу.
Класи A, B, C унаслідуються від базового класу, що
визначає інтерфейс взаємодії з усіма типами пристосо-
ванців.

7.4. Результати використання патерну


Якщо застосовувати цей патерн до свого додатку, ви
отримаєте дійсно значну економію пам’яті, навіть вра-
ховуючи те, що при отриманні доступу до об’єкта буде
марнування часу у методі фабрики (у нашому випадку в
GetObj). Але економія пам’яті вийде лише тому випадку,
якщо в об’єктах щонайменше будуть утримуватися вну-
трішні властивості, а за викликом будуть передаватися
зовнішні. Зовнішні властивості мають обчислюватися ал-
горитмами, у цьому полягає основна ідея патерна, «еконо-
мити пам'ять з допомогою обчислювальної потужності».
Отримувати доступ до об’єктів-пристосуванців варто
лише з допомогою методів фабрик, оскільки це додасть гнуч-
кості та можливості налаштувати об'єкт у методах фабрики.
Застосовувати патерн слід тоді, коли у вашому додатку
дійсно велика кількість об’єктів і коли їх стан можна опи-
сати зовнішніми властивостями, а зовнішні властивості
можна описати та привласнити за допомогою обчислень.

43
Урок №2

7.5. Практичний приклад


Розглянемо консольний додаток, який відображати-
ме і прораховувати результат битви двох армій.

Рисунок 21

44
7. Патерн Flyweight

Класи Human, Motor і Tank відрізняються лише зна-


ченнями внутрішніх властивостей та методом, що відо-
бражає на екрані бойову одиницю.
Об’єкт класу FactoryUnit буде зберігати в собі від нуля
до трьох об'єктів у вигляді Unit у спеціально для цього ство-
реної колекції ListUnits. Класи клієнтів зможуть отримати
доступ до об’єкта, викликавши з фабрики метод і передав-
ши в нього об’єкт перерахування, який і вкаже, який саме
Unit треба повернути як наслідок виклику метода.
Клас гравця (Player) буде використовувати фабрику
для отримання та відображення властивостей об’єктів.
Але користуватися всіма об’єктами гравців будуть на-
справді лише 3 екземпляри класів нащадків Unit, це має
економити пам’ять.
Основний клас Program містить метод Main, в якому
відбувається управління всією програмою, а також метод
Battle, відповідальний за математику, завдяки якій можна
дізнатися про результат битви армій двох гравців.
В матеріалах до цього уроку є папка Samples, в якій
ви зможете знайти реалізацію патерну Flyweight.

45
Урок №2

8. Патерн Proxy

Патерн Proxy часто називають патерном сурогатом.


Далі, основний клас, про який буде йти мова, називаєть-
ся сурогат, або проксі. Обидва терміни є правильними і
описують той самий клас / об'єкт.
Проксі — це деякий об'єкт, який забезпечує транзит-
ний доступ до іншого об'єкта.
Сурогат — це деякий об'єкт, який зовні нічим не від-
різняється від основного, але внутрішньої функціональ-
ності у ньому немає.
Об'єкт Сурогата, або проксі, зовні нічим не відрізня-
ється від об'єкта, який він представляє, але вся його вну-
трішня функціональність є лише деяким тунелем, через
який класи клієнта отримують доступ до основних об'єктів.
Також об'єкт сурогату або проксі можна називати за-
ступником об'єкта.

8.1. Мета патерну


Метою патерну є створення системи доступу до об'єк-
та через спеціальний об'єкт сурогату (рис. 22).

Клієнт Сурогат Цільовий


клас

Рисунок 22

Це дозволяє досягти більшої гнучкості роботи з об'єк-


том цільового класу.

46
8. Патерн Proxy

Якщо об'єкт цільового класу після створення буде за-


ймати багато місця і немає гарантії того, що об'єкт буде
необхідний в роботі програми. Можна створювати цільо-
вий об'єкт тільки коли клієнт перший раз викликає метод
з об'єкта сурогату, це прискорить швидкодію програми у
випадку, якщо об'єкт не буде використовуватися. А якщо
об'єкт і буде створено, то на етапі виконання програми
це буде не так «скрутно» для користувача.
Така система доступу дозволить також використову-
вати цільовий клас з більшим захистом (у сурогаті мож-
на виконувати різні перевірки параметрів, що прийма-
ються). Наприклад, якщо цільовий клас це калькулятор,
що приймає в аргументи методу два параметри і вико-
нує базові математичні операції. В сурогаті класу каль-
кулятор можна виконати перевірку, щоб не вийшло, що
калькулятору буде передана задача «поділити на нуль».
Можна використати структуру патерна проксі для
створення так званого «Посла» в інший простір імен. На-
приклад, цільовий клас описаний у просторі імен, який
з якихось причин не можливо (або незручно) підключи-
ти. У такому випадку можна створити сурогат, який буде
знаходитись у «потрібному» просторі імен, а всередині
сурогату буде створено об'єкт цільового класу з іншого
простору імен.

8.2. Причини виникнення патерну


Код одних програмістів повинен бути зрозумілий
іншим програмістам щодо синтаксичних і структурних
«традицій», якщо створювати додаток використовуючи

47
Урок №2

патерн проксі для доступу до об'єктів і в об'єктах суро-


гатів займатися перевіркою даних, а в цільовому класі
виконувати логіку. Потім досить легко пояснити іншому
програмісту, де виконуються перевірки, а де основна ло-
гіка. Взагалі, використовуючи патерни досить легко по-
яснити структуру додатка.
Напевно, вам вже доводилося бачити додатки, які піс-
ля початку запуску дуже довго «думають» і тільки через
5 або більше секунд починають відображати свій інтер-
фейс. Так виходить, тому що додаток відразу при старті
починає завантажувати всі свої модулі, створює всі ек-
земпляри класів, які знадобляться (або не знадобляться) у
роботі додатку. Для часткового вирішення такої проблеми
можна створити сурогат «масивного» об'єкта, створюва-
ти такий об'єкт при старті додатка. Сурогат це лише му-
ляж, який не є таким «важким», як цільовий об'єкт і тому
створюється швидше, а «важкий» об'єкт буде створений
тільки тоді, коли він буде дійсно необхідний. А необхід-
ність з'являється, коли класи клієнта будуть працювати
з об'єктом сурогату, який всі запити перенаправлятиме
на щойно створений цільовий об'єкт.

8.3. Структура патерну


Патерн Proxy передбачає наявність деякого об'єкта
(далі «цільовий клас»), до якого здійснюватиметься доступ
за допомогою спеціально створеного об'єкта сурогату.
Але об'єкт сурогату не має відрізнятися зовні від
об'єкта цільового класу, тому обидва класи мають бути
успадковані від одного інтерфейсу (рис. 23).

48
8. Патерн Proxy

Client MathProxy Math

Add(5,8)

Add(5,8)

13

13

Рисунок 23

У наведеному прикладі цільовий об'єкт Math створю-


ється одночасно з об'єктом сурогату, оскільки клас Math
не є «важким» і створюватиметься швидко.
Приклад показує, як за допомогою об'єкта сурогату
можна виконувати різні перевірки перед безпосередньою
передачею даних цільовому класу.

8.4. Результати використання патерну


Реалізувавши доступ до патерну через об’єкт сурога-
ту, ми отримуємо додатковий рівень роботи з цільовим
об’єктом. На цьому рівні ми можемо оптимізувати, ство-
рюючи цільові об’єкти в тій мірі, як вони будуть вико-
ристовуватися. Можна перевіряти дані перед передачею
в цільовий об'єкт. В об'єкті сурогату можна навіть вести
логування доступу до об'єкта (наприклад, вираховувати

49
Урок №2

кількість викликаних методів підсумовування на каль-


куляторі) (рис. 24).

Рисунок 24

8.5. Практичний приклад


Для кращого розуміння патерна ознайомимося зі
структурою додатка «магазин інформації». В архітектурі
програми є клас Shop, до якого здійснюється доступ че-

50
8. Патерн Proxy

рез клас ProxyShop. Клас Shop має метод, який приймає


рядок з ключем, а потім якщо це можливо, повертає ря-
док з інформацією.
Клас ProxyShop захищає клас Shop від можливості
його «брутфорсити». Також об'єкт Shop створюється тіль-
ки тоді, коли він буде необхідний у програмі, тобто коли
хтось спробує отримати інформацію про ключ.
Нижче наведена діаграма класів цієї програми (рис. 25).

Рисунок 25

В матеріалах до цього уроку є папка Samples, в якій


ви знайдете реалізацію патерну Proxy.

51
Урок №2

9. Аналіз і порівняння
структурних патернів

Ви вже вивчили усе про структурні патерни:


■ Adapter — патерн, який «адаптує» об'єкт під інший
інтерфейс для доступу до нього. Наприклад, в об'єкті
є метод Operation1, а нам потрібно зробити так, щоб
він називався OperationA. Метою патерну Adapter є
«редагування» інтерфейсу доступу до цільового об'єкта.
■ Bridge — патерн дозволяє відокремити абстракцію від
реалізації, коли є абстрактно описана ієрархія об'єктів і
потім буде реалізовуватися ієрархія під певну систему.
Метою патерну Bridge є побудова окремо абстракції та
реалізації, і надання клієнту абстракції, за допомогою
якої він зможе керувати реалізацією.
■ Composite  — структурний патерн, який виставляє
об'єкти за ієрархією. Метою цього патерну є побудова
ієрархічної структури для зберігання об'єктів.
■ Decorator — патерн дозволяє структурувати таким
чином, що декілька об'єктів відображаються як один.
І кількість внутрішніх об'єктів може змінюватись мит-
тєво.
■ Facade — структурний патерн, який повідомляє як
будувати великі додатки з дрібних незалежних підсис-
тем. Метою патерну є створення вузького і зрозумілого
інтерфейсу для роботи з підсистемою.

52
9. Аналіз і порівняння структурних патернів

■ Flyweight — патерн дозволяє економити місце у ви-


падку якщо в програмі є безліч дрібних об'єктів і їх
стан можна винести у зовнішні властивості, які об-
числюються алгоритмами.
■ Proxy — передбачає створення об’єкта сурогату для
цільового об’єкта, чим може забезпечити більшу гнуч-
кість, економію пам’яті та захист.
Підходити до використання патернів потрібно від-
штовхуючись від їх призначення, оскільки з першого по-
гляду може видатися, що патерни схожі з деяких власти-
востей, але так здається тільки тому, що деякі з них ма-
ють схожу структуру. Але кожен патерн має на меті ви-
користання. Наприклад, вам може здатися, що патерни
«фасад» та «проксі» дуже схожі, але призначені вони для
різних цілей. Мета патерна «фасад» — створити вузько
направлений інтерфейс роботи з підсистемою, а «проксі»
дозволяє захистити цільовий об'єкт.
Структурно патерни Composite і Decorator теж дуже
схожі, але необхідно відштовхуватися від цілей застосу-
вання, оскільки патерн Composite структурує об'єкти, а
патерн Decorator дозволяє створити окремі види функ-
ціональності та створити з них «один» об'єкт.
Часто доводиться бачити, як розробники не бачать різ-
ниці між патерном «фасадом» (Facade) і патерном «адап-
тер» (Adapter), тому що здається, що мета в них однакова,
а також змінити або модифікувати інтерфейс доступу до
об’єкта або об’єктів. Але адаптер дозволяє працювати зі
старим інтерфейсом доступу до об’єкта та використову-

53
Урок №2

вати новий, а патерн Facade створює новий інтерфейс,


більш цілеспрямований.
Важливо зазначити, що патерн — це не еталон струк-
тури програми. На практиці доводиться чути таке: «от у
нас тут архітектура, як у патерні Flyweight, але у фабриці
різні типи об’єктів повертаються із різних методів».

54
10. Домашнє завдання

10. Домашнє завдання

Домашнім завданням буде розробити три моделі до-


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

55
Урок №2
Структурні патерни

© Комп᾿ютерна Академія «Шаг», www.itstep.org

Усі права на фото-, аудіо- і відеотвори, що охороняються авторським правом і


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

You might also like