|
13. Ланцюжок Відповідальностей — Chain of responsibility
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 Системне програмування Системний аналіз Тестологія Тестування ПЗ Фреймворки Штучний інтелект
|
13. Ланцюжок Відповідальностей — Chain of responsibility
Уявіть, що ви пішли із своїми друзями в кафе. Кафе дещо специфічне — мало місця, і коли вам приносять якусь страву, зазвичай доводиться передавати її наступній людині за столом. Ваш найкращий друг сів найближче до краю, тому першим він і отримує до рук замовлення. Так як він мало спав зранку і любить поїсти м’ясця, то він ніколи не передесть вам м’ясної страви чи кави, допоки сам не насититься. Наступним після друга сидите ви, а далі ваша подружка, яка знаходиться біля стіни. Вона отримає все останньою, але, на щастя, вона хоче тільки капучіно, та й передавати їй уже не треба нікому. Ланцюжок Відповідальностей забезпечує обробку об’єкта, шляхом передачі його по ланцюжку доти, доки не буде здійснена обробка якоюсь із ланок. Я думаю що весь механізм патерну Ланцюжка Відповідальностей є зрозумілим — ми маємо набір обробників (handlers) або відвідувачів кафе, які вміють обробляти команду (command) — їжу у нашому випадку. Якщо обробити команду не вдається, то вона передається наступному обробітнику. Для прикладу із нашим кафе, загальним інтерфейсом відвідувача такого дивного кафе може бути такий базовий клас: Уривок коду 13.1. Дивний відвідувач кафе (обробник)
abstract class WierdCafeVisitor
{
public WierdCafeVisitor CafeVisitor { get; private set; }
protected WierdCafeVisitor(WierdCafeVisitor cafeVisitor)
{
CafeVisitor = cafeVisitor;
}
public virtual void HandleFood(Food food)
{
// Якщо не в змозі подужати їжу, передаємо її ближчому другові
if (CafeVisitor != null)
{
CafeVisitor.HandleFood(food);
}
}
}
Як бачимо, по замовчуванню їжа просто передається до наступного відвідувача у ланцюжку, якщо такий є. Уривок коду 13.2. Конкретний дивний відвідувач кафе — ваш кращий друг
class BestFriend : WierdCafeVisitor
{
public List<Food> CoffeeContainingFood { get; private set; }
public BestFriend(WierdCafeVisitor cafeVisitor) : base(cafeVisitor)
{
CoffeeContainingFood = new List<Food>();
}
public override void HandleFood(Food food)
{
if(food.Ingradients.Contains("Meat"))
{
Console.WriteLine(
"BestFriend: I just ate {0}. It was tasty.",
food.Name);
return;
}
if (food.Ingradients.Contains("Coffee") && CoffeeContainingFood.Count < 1)
{
CoffeeContainingFood.Add(food);
Console.WriteLine(
"BestFriend: I have to take something with coffee. {0} looks fine.",
food.Name);
return;
}
base.HandleFood(food);
}
}
Реалізації ще двох обробітників — Me та GirlFriend мають бути зрозумілими, але все ж таки наведемо реалізацію відвідувача-подружки: Уривок коду 13.3. Ваша подружка
class GirlFriend : WierdCafeVisitor
{
public GirlFriend(WierdCafeVisitor cafeVisitor) : base(cafeVisitor)
{
}
public override void HandleFood(Food food)
{
if(food.Name == "Cappuccino")
{
Console.WriteLine("GirlFriend: My lovely cappuccino!!!");
return;
}
// Базовий виклик base.HandleFood(food) для останнього обробітника-дівчини
// не має сенсу, тому можна викинути ексепшин або нічого не робити
}
}
Все відносно просто — дівчина хоче капучіно, але вона у ланцюжку остання, тому допоки ваш друг, який перший у ланцюжку, не вип’є щось із кофеїном, капучіно вона не отримає. Уривок коду 13.3. Замовляємо і передаємо
var cappuccino1 = new Food("Cappuccino", new List<string> {"Coffee", "Milk",
"Sugar"});
var cappuccino2 = new Food("Cappuccino", new List<string> {"Coffee", "Milk"});
var soup1 = new Food("Soup with meat", new List<string> {"Meat", "Water",
"Potato"});
var soup2 = new Food("Soup with potato", new List<string> {"Water", "Potato"});
var meat = new Food("Meat", new List<string> {"Meat"});
var girlFriend = new GirlFriend(null);
var me = new Me(girlFriend);
var bestFriend = new BestFriend(me);
bestFriend.HandleFood(cappuccino1);
bestFriend.HandleFood(cappuccino2);
bestFriend.HandleFood(soup1);
bestFriend.HandleFood(soup2);
bestFriend.HandleFood(meat);
Вивід:
BestFriend: I have to take something with coffee. Cappuccino looks fine.
GirlFriend: My lovely cappuccino!!!
BestFriend: I just ate Soup with meat. It was testy.
Me: I like Soup. It went well.
BestFriend: I just ate Meat. It was testy.
Як видно із виводу в консоль, дівчина отримала тільки друге капучіно, а ви були змушені їсти суп без м’яса :) Що цікаво, мо ми можемо після моєї дівчини підчепити ще один обробітник — скажімо мішечок для собачки. Туди скидатимемо те, що ніхто не захоче їсти. Для цього прийдеться трішки змінити клас, щоб він мав метод на подобі SetNextCafeVisitor для динамічної додачі обробників.
По матеріалам книги Андрія Будая "Дизайн патерни – просто, як двері". Матеріал розміщується за домовленістю з автором.
Зверніть увагу на додаткові посиланняЯкщо вас цікавить...Головний розділСторінки, близькі за змістомзагрузка...
|
Сторінки, близькі за змістом ![]() Шаблони проектування програмного забезпечення (англ. software design patterns) — ефективні способи вирішення задач проектування програмного забезпечення. Шаблон не є закінченим зразком, який можна безпосередньо транслювати в програмний код. Об'єктно-орієнтований шаблон найчастіше є зразком вирішення проблеми і відображає відношення між класами та об'єктами, без вказівки на те, як буде зрештою реалізоване це відношення. |
|
Copyright © 2008—2026 Портал Знань.
При використанні матеріалів посилання, для інтернет-ресурсів — гіперпосилання, на Znannya.org обов'язкове.
Зв'язок
|
НТУУ "КПІ" Інженерія програмного забезпечення КПІ Лабораторія СЕТ |
|