23. Відвідувач — Visitor
ADO в Delphi AJAX Android C++ CakePHP CMS COM CSS Delphi Flash Flex HTML Internet Java JavaScript MySQL PHP RIA SCORM Silverlight SQL UML XML Бази даних Веб-розробка Генетичні алгоритми ГІС Гітара Дизайн Економіка Інтелектуальні СДН Колір Масаж Математика Медицина Музика Нечітка логіка ООП Патерни Подання знань Розкрутка сайту, SEO САПР Сесії в PHP Системне програмування Системний аналіз Тестологія Тестування ПЗ Фреймворки Штучний інтелект
|
23. Відвідувач — VisitorУявімо собі, що ви нарешті спромоглися створити свою власну компанію, і оскільки вона пристойного розміру, ви вирішили орендувати для неї цілу будівлю. У нас держава дуже хороша і дбає про підприємства. А щоб у підприємств усе відповідало вимогам, постійно висилаються різноманітні перевірки. Причому правила, за якими перевіряють ваше підприємство, постійно змінюються. Найближчим часом вам слід буде прийняти багато відвідувачів (visitors), таких як електрик (electrician), сантехнік (plumber), податківець і так далі... Усі вони будуть перевіряти вашу будівлю вздовж і в поперек, проходячи від поверха до поверха, від кімнати до кімнати. Я підозрюю, що якась певна схема класів у вас уже появилася у голові. Якщо так, то у мене є наступне питання: де має жити логіка певної перевірки будівлі? Чи має будівля знати, як перевіряти електричні щитки, чи це має знати електрик, або чи має знати кімната, як перевірити включателі, чи це так само робота електрика? Звичайно що електрик, який і є відвідувачем, інкапсулює логіку перевірки певних елементів (elements) вашої будівлі. Відвідувач (Visitor) дозволяє відділити певний алгоритм від елементів, на яких алгоритм має бути виконаний, таким чином ми можемо легко додати або ж змінити алгоритм без змін до елементів системи. Як на мене, це і є однією із найбільш помітних переваг цього патерну. Отже, як і було згадано вище, інкапсульована логіка живе у конкретному відвідувачі. Ця логіка може бути застосована до елементів системи. Основу цього дизайн патерну можна вибудувати на двох інтерфейсах. Ось вони: Уривок коду 24.1. IVisitor та IElementvisitor); }Уривок коду 24.1. IVisitor та IElement interface IVisitor { void Visit(OfficeBuilding building); void Visit(Floor floor); void Visit(Room room); } interface IElement { void Accept(IVisitor У нашому прикладі ElectricitySystemValidator є однією із конкретних реалізацій інтерфейсу IVisitor, яка може виглядати як наведений нижче код: Уривок коду 24.1. Один із відвідувачів → електрикstate.", building.BuildingName, electricityState)); } public void Visit(Floor floor) { Console.WriteLine( string.Format("Diagnosting electricity on floor {0}.", floor.FloorNumber)); } public void Visit(Room room) { Console.WriteLine( string.Format("Diagnosting electricity in room {0}.", room.RoomNumber)); } }class ElectricitySystemValidator : IVisitor { public void Visit(OfficeBuilding building) { var electricityState = (building.ElectricitySystemId > 1000) ? "Good" : "Bad"; Console.WriteLine( string.Format("Main electric shield in building {0} is in {1} Про що говорить нам цей клас? Ми зауважили, що у відповідності до інтерфейсу IVisitor в одному відвідувачі є три методи, кожен із яких описує логіку перевірки для одного із елементів. Виходячи із цього, ми можемо з чистою совістю проводити нашого відвідувача із поверху на поверх та з кімнати до кімнати. Клас PlumbingSystemValidator схожий на ElectricitySystemValidator, але в своїй логіці бере до уваги вік будівлі, щоб приблизно оцінити на скільки сантехнічна частина справна. Що ще цікаво про цей клас, так це те, що він нічого не робить у кімнатах. Звісно, якщо ваше підприємство є якимось хім-заводом, сантехніку доведеться пройтися по всіх кімнатах. До цього часу вже стало зрозуміло, що структура будівлі обхідна. Все починається із будівлі (OfficeBuilding), яка має поверхи (Floors), і кожен із поверхів може мати багато кімнат. Глянемо на імплементацію поверху. Уривок коду 24.1. Один із елементів будівні — поверхvisitor) { visitor.Visit(this); foreach (var room in Rooms) { room.Accept(visitor); } } }class Floor : IElement { private readonly IList<Room> _rooms = new List<Room>(); public int FloorNumber { get; private set; } public IEnumerable<Room> Rooms { get { return _rooms; } } public Floor(int floorNumber) { FloorNumber = floorNumber; } public void AddRoom(Room room) { _rooms.Add(room); } public void Accept(IVisitor Як можна побачити, цей клас мітить метод Accept, який вимагається інтерфейсом і який приймає відвідувача. В середині цього методу ми виконуємо наш алгорим і, якщо треба, передаємо нашого відвідувача «по колу». Як бачимо, ніякі технічні перевірки не виконуються напряму у цьому класі, тому ми можемо бути певні, що якщо у майбутньому слід буде змінити спосіб перевірки електросистеми у кімнаті, то це буде зроблено у відвідувачі без будь-яких впливів на клас кімнати. OfficeBuiling є досить подібним класом, хіба що має багато інших додаткових властивостей. Room взагалі є простим класом, який не агрегує чи компонує інших елементів. Глянемо на код використання дизайн патерну: Уривок коду 24.1. Маємо будівлю із 2-ма поверхами, на кожному є по 3 кімнати. Запускаємо у будівлю електрика і сантехніка як відвідувачів
var floor1 = new Floor(1);
floor1.AddRoom(new Room(100));
floor1.AddRoom(new Room(101));
floor1.AddRoom(new Room(102));
var floor2 = new Floor(2);
floor2.AddRoom(new Room(200));
floor2.AddRoom(new Room(201));
floor2.AddRoom(new Room(202));
var myFirmOffice = new OfficeBuilding("[Design Patterns Center]", 25, 990);
myFirmOffice.AddFloor(floor1);
myFirmOffice.AddFloor(floor2);
var electrician = new ElectricitySystemValidator();
myFirmOffice.Accept(electrician);
var plumber = new PlumbingSystemValidator();
myFirmOffice.Accept(plumber);
Вивід:state. Diagnosting electricity on floor 1. Diagnosting electricity in room 100. Diagnosting electricity in room 101. Diagnosting electricity in room 102. Diagnosting electricity on floor 2. Diagnosting electricity in room 200. Diagnosting electricity in room 201. Diagnosting electricity in room 202. Plumbing state of building [Design Patterns Center] probably is in Good condition, since builing is New. Diagnosting plumbing on floor 1. Diagnosting plumbing on floor 2.Main electric shield in building [Design Patterns Center] is in Bad UML діаграма класівЧим більше я пишу про дизайн патерни, тим більше я розумію що UML діаграми часто можуть ввести в оману. Ті діаграми, що представлені в GoF книжці насправді хороші, але вони зображають одні із найбільш частих випадків застосування певного патерну. Таким чином, Відвідувача найчастіше зображають як один базовий клас із двома похідними. Базовий клас визначає, що похідні мають реалізовувати «відвідування» елементів системи. Елемент системи може мати декілька реалізацій також.
UML-діаграма 14. Стандартна діаграма Відвідувача Але коли я собі думаю, як інакше цей дизайн патерн може бути реалізований, то діаграми будуть виглядати зовсім інакше. Зокрема, із використанням Компонувальника, можна реалізувати тільки один клас для елемента, який є деревовидною структурою і містить вкладені елементи. Або ваша програма може містити один клас для відвідувача і один для елемента. За цим криється патерн, але не так і просто його розгледіти. Хоча й навіщо?... Однією із переваг патерну є те, що він відоклемлює алгоритм від елементів, до яких він має бути застосований, але це одночано й недолік, оскільки інтерфейс елемента має бути досить розвинений для нормальної роботи Відвідувача. Ще одним недоліком є порушення зв’язності системи, оскільки із використанням цього патерну прийдеться добавляти велику кількість методів в елементи, які будуть відвідуватися.
По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Зверніть увагу на додаткові посиланняЯкщо вас цікавить...Головний розділСторінки, близькі за змістомзагрузка...
|
Сторінки, близькі за змістом Шаблони проектування програмного забезпечення (англ. software design patterns) — ефективні способи вирішення задач проектування програмного забезпечення. Шаблон не є закінченим зразком, який можна безпосередньо транслювати в програмний код. Об'єктно-орієнтований шаблон найчастіше є зразком вирішення проблеми і відображає відношення між класами та об'єктами, без вказівки на те, як буде зрештою реалізоване це відношення. |
Copyright © 2008—2024 Портал Знань.
При використанні матеріалів посилання, для інтернет-ресурсів — гіперпосилання, на Znannya.org обов'язкове.
Зв'язок
|
НТУУ "КПІ" Інженерія програмного забезпечення КПІ Лабораторія СЕТ |
|