Я читал о принципале OCP и о том, как использовать шаблон стратегии для этого.
Я собирался попытаться объяснить это нескольким людям, но единственный пример, который я могу придумать, - это использование разных классов валидации в зависимости от того, в каком статусе находится «заказ».
Я прочитал пару статей в Интернете, но они обычно не описывают настоящую причину использования стратегии, например, создание отчетов / счетов / проверки и т. Д.
Есть ли какие-нибудь примеры из реального мира, где, по вашему мнению, распространен шаблон стратегии?
источник
Cipher C =null; if (file.size() <= 2048) { C = new InMemoryCipherStrategy(); } else { c= SwaptToDiskCipher (); }
CipherFactory
может смутить тех, кто не знаком с шаблоном Стратегия.Опять же, старый пост, но все еще появляется при поиске, поэтому я добавлю еще два примера (код на C #). Мне очень нравится шаблон «Стратегия», поскольку он много раз спасал меня, когда менеджеры проектов говорили: «Мы хотим, чтобы приложение выполняло« X », но« X »еще не ясно, и это может измениться в ближайшем будущем. " В этом видео, объясняющем схему стратегии , в качестве примера используется StarCraft.
Материалы, относящиеся к этой категории:
Сортировка: мы хотим отсортировать эти числа, но не знаем, будем ли мы использовать BrickSort, BubbleSort или другую сортировку.
Проверка: нам нужно проверять элементы в соответствии с «некоторым правилом», но еще не ясно, каким будет это правило, и мы можем подумать о новых.
Игры: мы хотим, чтобы игрок либо шел, либо бежал, когда он двигается, но, возможно, в будущем он также сможет плавать, летать, телепортироваться, копаться под землей и т. Д.
Хранение информации: мы хотим, чтобы приложение сохраняло информацию в базе данных, но позже ему может потребоваться сохранить файл или сделать веб-вызов
Вывод: нам нужно вывести X в виде простой строки, но позже это может быть CSV, XML, JSON и т. Д.
Примеры
У меня есть проект, в котором пользователи могут назначать продукты людям в базе данных. Это назначение продукта человеку имеет статус «Утверждено» или «Отклонено», что зависит от некоторых бизнес-правил. Например: если пользователь назначает продукт человеку определенного возраста, его статус должен быть отклонен; Если разница между двумя полями в элементе больше 50, его статус отклоняется и т. Д.
Сейчас, на момент разработки, эти бизнес-правила еще не полностью ясны, и в любой момент могут появиться новые правила. Сила шаблона stragety в том, что я создал RuleAgent, которому дан список IRules.
В момент назначения продукта человеку я создаю RuleAgent, даю ему список правил (все они реализуют IRule) и прошу его подтвердить назначение. Он будет проходить по всем своим правилам. Поскольку все они реализуют один и тот же интерфейс, у всех есть
IsApproved
метод и возвращают false, если какой-либо из них возвращает false.Теперь, когда, например, внезапно подходит менеджер и говорит, что нам также нужно отклонить все задания стажерам или все задания людям, работающим сверхурочно ... Вы создаете новые классы следующим образом:
Вы видите, что вам не нужно постоянно добавлять или удалять операторы if или код, просто создайте новый класс правил, реализующий интерфейс IRUle, и при необходимости отключите их.
Другой замечательный пример: серия видео Скотта Аллена на http://www.asp.net/mvc/pluralsight, где он использует шаблон стратегии в части приложения, посвященной модульному тестированию.
Он создает веб-сайт, на котором отображаются элементы в зависимости от их популярности. Однако «популярным» может быть множество вещей (большинство просмотров, большинство подписчиков, дата создания, наибольшая активность, наименьшее количество комментариев и т. Д.), И в случае, если руководство еще не знает, как сделать заказ, и может захотеть поэкспериментировать с разными заказы на более поздний срок. Вы создаете интерфейс (IOrderAlgorithm или что-то в этом роде) с помощью метода заказа и позволяете объекту Orderer делегировать упорядочивание конкретной реализации интерфейса IOrderAlgorithm. Вы можете создать "CommentOrderer", "ActivityOrderer" и т. Д. И просто отключить их, когда появятся новые требования.
источник
InternRule
сейчас, но как мы запускаемOvertimeRule
? Как мы убедимся , что независимо логики под названиемOvertimeRule.IsApproved
теперь звонкиInternRule.IsApproved
?Основные примечания:
Стратегия - это шаблон поведенческого проектирования. Он используется для переключения между семейством алгоритмов.
Этот шаблон содержит один абстрактный интерфейс стратегии и множество конкретных реализаций стратегии ( алгоритмов ) этого интерфейса.
Приложение использует только интерфейс стратегии . В зависимости от некоторого параметра конфигурации конкретная стратегия будет привязана к интерфейсу .
Схема UML из википедии
Один реальный пример: авиакомпании, предлагающие скидки в течение нескольких месяцев (июль-декабрь) . Вы можете получить один тариф модуль , который определяет варианты ценообразования в зависимости от номера месяца.
Взгляните на простой пример. Этот пример можно распространить на онлайн-приложения для розничной торговли, которые легко предоставляют скидки на товары в корзине в особые дни / счастливые часы.
вывод:
Полезные статьи:
стратегияшаблон от dzone
шаблон стратегии по источникам
источник
Я могу вспомнить несколько довольно простых примеров:
Сжатие данных. У вас может быть интерфейс ICompressor, единственный метод которого выглядит примерно так:
byte [] compress (byte [] вход);
Ваши конкретные классы сжатия могут быть такими как RunLengthCompression, DeflateCompression и т. Д.
источник
Одним из распространенных способов использования шаблона стратегии является определение пользовательских стратегий сортировки (на языках без функций высшего порядка), например, для сортировки списка строк по длине в Java, передавая анонимный внутренний класс (реализация интерфейса стратегии):
Аналогичным образом стратегии можно использовать для собственных запросов к объектным базам данных, например, в db4o:
источник
У меня есть приложение, которое каждый день синхронизирует свою пользовательскую базу с нашим корпоративным каталогом. Пользователи имеют право или не имеют права в зависимости от их статуса в университете. Каждый день программа инициализации проходит и проверяет, что те, кто должен иметь право, были подготовлены в приложении, а те, кто не получил, деинициализированы (на самом деле в соответствии с алгоритмом постепенной деградации, но это не относится к делу). В субботу я делаю более тщательное обновление, которое синхронизирует некоторые свойства каждого пользователя, а также проверяет, соответствуют ли они требованиям. В конце месяца я выполняю некоторую обработку счетов на основе использования за этот месяц.
Для этой синхронизации я использую составной шаблон стратегии. Основная программа в основном выбирает основную стратегию в зависимости от дня недели (синхронизировать только изменения / синхронизировать все) и времени семестра относительно академического календаря. Если цикл выставления счетов заканчивается, он также составляет его со стратегией выставления счетов. Затем он запускает выбранную стратегию через стандартный интерфейс.
Не знаю, насколько это распространено, но мне показалось, что это идеально подходит для шаблона стратегии.
источник
Я знаю, что это старый вопрос, но я думаю, что у меня есть еще один интересный пример, который я реализовал недавно.
Это очень практичный пример шаблона стратегии, используемого в системе доставки документов.
У меня была система доставки PDF, которая получила архив, содержащий множество документов и некоторые метаданные. Основываясь на метаданных, он решил, куда поместить документ; скажем, в зависимости от данных, я мог бы хранить документ в
A
,B
илиC
системах хранения данных, или смесь из трех.Эту систему использовали разные клиенты, и у них были разные требования к откату / обработке ошибок в случае ошибок: один хотел, чтобы система доставки останавливалась при первой ошибке, оставляла все документы уже доставленными в их хранилища, но останавливала процесс и не доставляла ничего больше ; другой хотел, чтобы он откатился
B
в случае ошибок при сохраненииC
, но оставил то, что уже было доставленоA
. Несложно представить, что у третьего или четвертого тоже будут другие потребности.Чтобы решить эту проблему, я создал базовый класс доставки, который содержит логику доставки, а также методы отката данных со всех хранилищ. Эти методы фактически не вызываются системой доставки напрямую в случае ошибок. Вместо этого класс использует внедрение зависимостей для получения класса «Стратегия отката / обработки ошибок» (на основе клиента, использующего систему), который вызывается в случае ошибок, который, в свою очередь, вызывает методы отката, если это подходит для этой стратегии.
Сам класс доставки сообщает, что происходит, классу стратегии (какие документы были доставлены в какие хранилища и какие произошли сбои), и всякий раз, когда возникает ошибка, он спрашивает стратегию, продолжать или нет. Если в стратегии сказано «остановить это», класс вызывает метод стратегии «cleanUp», который использует ранее сообщенную информацию, чтобы решить, какие методы отката вызывать из класса доставки, или просто ничего не делает.
Итак, у меня теперь есть две разные стратегии: одна
QuitterStrategy
(которая завершает работу при первой ошибке и ничего не очищает), а другая -MaximizeDeliveryToAStrategy
(которая пытается как можно больше не прерывать процесс и никогда не откатывать данные, доставленные в хранилищеA
, но откатывает вещи изB
if доставки вC
неудачную).Насколько я понимаю, это один из примеров паттерна стратегии. Если вы (да, читаете) думаете, что я ошибаюсь, оставьте комментарий ниже и дайте мне знать. Мне любопытно, что можно считать «чистым» использованием шаблона стратегии, и какие аспекты моей реализации нарушают определение. Я думаю, это выглядит немного забавно, потому что интерфейс стратегии немного толстоват. Во всех примерах, которые я видел до сих пор, используется только один метод, но я все же считаю, что он инкапсулирует алгоритм (если часть бизнес-логики может считаться алгоритмом, что, как мне кажется, так и есть).
Поскольку стратегия также уведомляется о событиях во время выполнения доставки, она также может считаться наблюдателем. , но это уже другая история.
После небольшого исследования кажется, что это "составной шаблон" (например, MVC, шаблон, который использует несколько шаблонов проектирования определенным образом), называемый Советчиком . Это советник относительно того, должна ли доставка продолжаться или нет, но это также активный обработчик ошибок, поскольку он может откатить данные, когда их попросят.
В любом случае, это довольно сложный пример, из-за которого у вас может возникнуть ощущение, что использование шаблона стратегии слишком простое / глупое. Он может быть действительно сложным и даже более применимым при использовании вместе с другими шаблонами.
источник
Шаблон стратегии - это наиболее часто используемый шаблон специально для алгоритмов проверки и сортировки.
Позвольте мне объяснить на простом практическом примере
Тестовый код для этого:
Тот же пример взят из http://coder2design.com/strategy-pattern/
источник
Хорошим примером шаблона стратегии может быть игра, в которой у нас могут быть разные персонажи, и каждый персонаж может иметь несколько видов оружия для атаки, но одновременно может использовать только одно оружие. Итак, у нас есть персонаж в качестве контекста, например Король, Командир, Рыцарь, Солдат и оружие в качестве стратегии, где атака () может быть методом / алгоритмом, который зависит от используемого оружия. Итак, если бы конкретными классами оружия были Sword, Axe, Crossbow, BowAndArrow и т. Д., Все они реализовали бы метод attack (). Я уверен, что дальнейшие объяснения не нужны.
источник
Я использовал стратегический подход в довольно сложном движке в приложении, которое является хорошим примером. По сути, роль движка заключалась в том, чтобы сначала найти список людей, у которых был виджет, а вторая роль заключалась в том, чтобы выяснить, какие 10 лучших людей с виджетом были на основе неизвестного количества параметров (таких как цена, расстояние до предыдущего бизнеса вместе , количество на складе, варианты доставки и т.д. и т.п ...)
По сути, мы разбили проблему на две стратегии, первая из которых - это извлечение данных, поскольку мы знали, что у нас есть несколько источников наших виджетов, и нам нужно иметь возможность получать данные и преобразовывать их в общую структуру.
Затем мы также поняли, что у нас было несколько алгоритмов, некоторые из которых были основаны на взвешивании параметров, другие были очень странными и уместными, и я не мог отдать им должное, не вытаскивая видео и диаграммы, и вы понимаете, у нас было много алгоритмов для выбор лучших людей.
Сама наша служба - это то, что по сути определяло входные и выходные данные и выполняла некоторую нормализацию данных, а также использовала шаблон поставщика для подключения поставщиков данных для конкретных приложений и поставщиков алгоритмов, которые использовали эту стратегию. Это была довольно эффективная система.
У нас были споры о том, используем ли мы стратегию или шаблонный шаблон, которые мы так и не нашли.
источник
Вы уверены, что статус «заказа» не является шаблоном состояния? У меня есть подозрение, что заказ не будет обрабатываться по-разному в зависимости от его статуса.
Возьмем, к примеру, метод Доставка по заказу:
Лучший пример паттерна состояний (и других паттернов), который я нашел, был в книге « Head First Design Patterns », которая потрясающая. На втором месте будет серия шаблонов ведения блога Дэвида Кампса .
источник
Допустим, вы хотите написать алгоритм для вычисления n-го X- дня данного месяца и года, например, второго понедельника октября 2014 года. Вы хотите использовать класс Android Time
android.text.format.Time
для представления даты, но вы также хотите написать общий алгоритм это также может относиться кjava.util.Calendar
.Вот что я сделал.
В DatetimeMath.java:
В TimeMath.java:
В OrdinalDayOfWeekCalculator.java класс с универсальным алгоритмом:
В моем приложении для Android я бы назвал что-то вроде
Если я хочу повторно использовать тот же алгоритм для
java.util.Calendar
, я бы просто написал класс CalendarMath, который реализует три метода в DatetimeMath, а затем использовал быисточник
источник
Несколько недель назад я добавил общий интерфейс Java, который был реализован одним из наших доменных объектов. Этот объект домена был загружен из базы данных, и представление базы данных было звездообразной схемой с примерно 10+ ветвями. Одним из последствий наличия такого тяжелого объекта домена является то, что нам пришлось создать другие объекты домена, которые представляли ту же схему, хотя и менее тяжелые. Поэтому я заставил другие легкие объекты реализовать тот же интерфейс. Иначе говоря, у нас было:
Изначально я хотел использовать
CollectibleElephant
для сортировкиElephant
s. Довольно быстро мои товарищи по команде началиCollectibleElephant
выполнять проверки безопасности, фильтровать их по мере их отправки в графический интерфейс и т. Д.источник
Нам пришлось создать сторонний интерфейс инициализации для корпоративной платформы с очень сложной базой данных. Предоставление данных для подготовки представляло собой список наших типов данных, которые были помещены в приоритетную очередь в нашем приложении, чтобы их можно было записать в базу данных в правильном порядке из-за зависимостей.
Тогда процесс записи этих данных был довольно простым: продолжайте появляться в верхней части очереди приоритетов, а затем выбирайте стратегию в зависимости от типа извлекаемого объекта.
источник
Из википедии
В приложении Windows Paint вы можете увидеть шаблон стратегии, в котором вы можете независимо выбирать форму и цвет в разных разделах. Здесь форма и цвет - это алгоритмы, которые можно изменять во время выполнения.
Если вы хотите нарисовать круг с красным цветом, вместо того, чтобы предоставлять опцию «Красный круг», они позволяют вам выбрать круг и цвет по вашему выбору.
Без стратегии шаблон увеличит количество классов с декартовым произведением формы и цвета. Также интерфейс меняется для каждой реализации.
источник
Представьте, например, шутер с противниками ИИ. Вы хотите, чтобы они постоянно сражались по-разному, в зависимости от того, что происходит ... С помощью шаблона стратегии вы можете непрерывно зацикливаться и динамически изменять способ выполнения определенного действия.
источник