Я знаю, що це старе запитання, але, думаю, у мене є ще один цікавий приклад, який я впровадив нещодавно.
Це дуже практичний приклад шаблону стратегії, який використовується в системі доставки документів.
У мене була система доставки PDF, яка отримала архів, що містить безліч документів та деякі метадані. Виходячи з метаданих, він вирішив, куди помістити документ; скажімо, в залежності від даних, я міг би зберігати документ в A, BабоC системах зберігання даних, або суміш з трьох.
Різні клієнти використовували цю систему, і вони мали різні вимоги до відкоту / обробки помилок у разі помилок: один хотів, щоб система доставки зупинилася при першій помилці, залишила всі документи вже доставленими у своїх сховищах, але зупинила процес і не доставляла нічого іншого ; інший хотів, щоб він відкотився Bна випадок помилок при зберіганні C, але залиште все, що вже було доставлено A. Неважко уявити, що третій чи четвертий також матимуть різні потреби.
Щоб вирішити проблему, я створив базовий клас доставки, який містить логіку доставки, а також методи відкочування матеріалів із усіх сховищ. Ці методи фактично не викликаються системою доставки безпосередньо у випадку помилок. Натомість клас використовує ін’єкцію залежності для отримання класу "Стратегія відкоту / обробки помилок" (на основі замовника, що використовує систему), який викликається у разі помилок, що, в свою чергу, викликає методи відкоту, якщо це підходить для цієї стратегії.
Клас доставки сам повідомляє про те, що відбувається з класом стратегії (які документи були доставлені до яких сховищ і які помилки траплялися), і щоразу, коли виникає помилка, він запитує стратегію, продовжувати чи ні. Якщо в стратегії сказано "зупиніть", клас викликає метод "cleanUp" стратегії, який використовує інформацію, повідомлену раніше, щоб вирішити, які методи відкату викликати з класу доставки, або просто нічого не робити.
rollbackStrategy.reportSuccessA(...);
rollbackStrategy.reportFailureB(...);
if (rollbackStrategy.mustAbort()) {
rollbackStrategy.rollback(); // rollback whatever is needed based on reports
return false;
}
Отже, у мене є дві різні стратегії: одна - це QuitterStrategy(яка закриває першу помилку і нічого не очищає), а друга - MaximizeDeliveryToAStrategy(яка намагається якомога більше не переривати процес і ніколи не відмовляти речі, що доставляються в пам’ять A, але відкат речі з Bдоставки доC не вдається).
Наскільки я розумію, це один із прикладів стратегії. Якщо ви (так, читаєте) вважаєте, що я помиляюся, будь ласка, коментуйте нижче та повідомте мене. Мені цікаво, що може означати "чисте" використання шаблону стратегії, і які аспекти моєї реалізації порушують це визначення. Я думаю, це виглядає трохи смішно, тому що стратегічний інтерфейс трохи жирний. У всіх прикладах, які я бачив до цього часу, використовується лише один метод, але я все ще думаю, що це інкапсулює алгоритм (якщо частину бізнес-логіки можна вважати алгоритмом, що, на мою думку, є).
Оскільки стратегія також повідомляється про події під час виконання доставки, її також можна вважати спостерігачем , але це вже інша історія.
З невеликого дослідження, здається, що це "складений шаблон" (наприклад, MVC, шаблон, який використовує декілька шаблонів дизайну внизу певним чином), який називається Advisor . Це радник щодо продовження доставки чи ні, але це також активний обробник помилок, оскільки він може відмовляти речі, коли про це просять.
У будь-якому випадку, це досить складний приклад, який може викликати у вас відчуття, що звичаї стратегії є надто простими / безглуздими. Він може бути справді складним і навіть більш застосовним, якщо його використовувати разом з іншими візерунками.