Разное

C паттерн стратегия: Стратегия (Strategy) | Паттерны в C# и .NET

Содержание

Стратегия

Также известен как: Strategy

Суть паттерна

Стратегия — это поведенческий паттерн проектирования, который определяет семейство схожих алгоритмов и помещает каждый из них в собственный класс, после чего алгоритмы можно взаимозаменять прямо во время исполнения программы.

Постановка Задачи:(из Фримэна)

 Смоделировать пруд, в котором
плавают и крякают утки разных видов. 

Реализация.

 ПЕРВЫЙ СПОСОБ (Стандартный прием
ООП)

—Определяем суперкласс УТКА(DUCK), на основе которого объявляются
типы конкретных видов уток.

Но, затем компания
решила добавить для уток возможность летать.

 И
тут получилось, что по экрану летают все резиновые утки. Т.е. не было учтено,
что метод fly()  должен быть унаследован не всеми производным
классами.Новое
поведение, добавленное в суперкласс Duck,
оказалось не подходящим для некоторых производных классов. И теперь в программе
начали летать неодушевленные объекты

 Итак, стало понятно, что
наследование не решит проблему – т.к. продукт должен обновляться каждые 6
месяцев, и придется переопределять методы fly()
и quack() для каждого нового производного
класса.

Следующая идея: 

—- аналогично можно определить
интерфейс IQuackable, потому что не все утки крякают.
—- исключить метод fly() из суперкласса Duck и определить интерфейс IFlyable() с методом fly().
Только те утки, которые должны
летать, реализуют интерфейс и содержат метод fly().

Первый принцип
проектирования

—Реализация интерфейсов решат
проблему частично, резиновые утки прекращают летать, но полностью исключается
возможность повторного использования кода этих аспектов поведения – а
следовательно. Создает другой кошмар из области сопровождения.Не говоря уже о том, что летающие
утки могут летать по-разному. Для подобных ситуаций существует полезный принцип
проектирования.

—Первый принцип проектирования:
выделите переменные составляющие и инкапсулируйте их, чтобы позднее их можно
было изменять или расширять без воздействия на постоянные составляющие.

Вернемся к нашему
проекту.

—Отделяем переменные составляющие.

—Мы знаем, что fly() и quack()
– части класса Duck, изменяющиеся в зависимости от
производного класса. Чтобы отделить эти аспекты поведения от класса Duck, мы вынесем оба метода за пределы
класса Duck и создадим новый набор классов для
представления каждого аспекта.

Интеграция
поведения с классом Duck.

У
новой структуры есть одна принципиальная особенность:

—класс
Duck теперь делегирует свои аспекты
поведения(вместо простого использования методов, определенных в классе Duck или его подклассах).

Вот
как это делается:

—сначала
в класс Duck включаются две переменные
экземпляров IFlyBehavlor и IQuackBehavlor, объявленные с типом интерфейса, а
не с типом конкретного класса реализации. Каждый объект на стадии выполнения
присваивает этим переменным полиморфные значения, соответствующие конкретному
типу поведения (FlyWithWings, Squeak
и т. д.).

—методы fly(), quack()
удаляются из класса Duck(и всех подклассов), потому что это
поведение перемещается в классы IFlyBehavlor 
и QuackBehavlor

—в классе Duck эти методы заменяются на perfomFly() и perfomQuack().

  1.    Duck
  2.    IFlyBehavlor  flyBehavlor
  3.    IQuackBehavlor  quackBehavlor
  4.    perfomQuack()
  5.    swim()
  6.    display()
  7.    perfomFly()

 //другие методы

Используйте паттерн
Стратегия, когда:

  1. Имеется
    много родственных классов, отличающихся только поведением. Стратегия позволяет конфигурировать класс, задав одно из возможных поведений;
  2. Вам
    нужно иметь несколько разных вариантов алгоритма. Например, можно определить
    два варианта алгоритма, один из которых требует больше времени, а другой —
    больше памяти. Стратегии разрешается применять, когда варианты алгоритмов
    реализованы в виде иерархии классов;
  3. В
    алгоритме содержатся данные, о которых клиент не должен знать. Используйте
    паттерн стратегия, чтобы не раскрывать сложные, специфичные для алгоритма
    структуры данных;
  4. В
    классе определено много поведений, что представлено разветвленными условными
    операторами. В этом случае проще перенести код из ветвей в отдельные классы
    стратегий.

Выбор реализации.

  1.  Стратегии могут предлагать
    различные реализации одного и того же
    поведения. Клиент вправе выбирать
    подходящую стратегию в зависимости от своих требований к быстродействию и
    памяти;
  2.  Клиенты должны «знать» о различных
    стратегиях. Потенциальный недостаток этого паттерна в том, что для выбора
    подходящей стратегии клиент должен понимать, чем отличаются разные стратегии.
    Поэтому наверняка придется раскрыть клиенту некоторые особенности реализации.
    Отсюда следует, что паттерн стратегия стоит применять лишь тогда, когда
    различия в поведении имеют значение для клиента;


Обмен информацией
между стратегией и контекстом

 Интерфейс класса Strategy разделяется всеми подклассами ConcreteStrategy — неважно, сложна или тривиальна
их реализация. Поэтому вполне вероятно, что некоторые стратегии не будут
пользоваться всей передаваемой им информацией, особенно простые. Это означает,
что в отдельных случаях контекст создаст и инициализирует параметры, которые
никому не нужны. Если возникнет проблема, то между классами Strategy и Context
придется установить более тесную связь;

СТРАТЕГИЯ
ТЕХНИЧЕСКИЕ ХАРАКТЕРИСТИКИ ПАРАМЕТРЫ
Вспомогательные переменные: 904 904 904 9044 Закрытие [i — 1] Короткие сделки: Close [i — 1]> High [i — 2].
Индекс: i ~ Текущий бар.
Фильтр: НЕТ
Вход: Длинные сделки: стоп-ордер на покупку размещается на один тик выше максимума [i — 1].
Короткие сделки: стоп-ордер на продажу размещается на один тик ниже минимума [i — 1].
Индекс: i ~ Текущий бар.
Выход: Время Выход: n день закрытия, n = Time_Index.
Целевой выход: Длинные сделки: Продажа на закрытии осуществляется, если Close [i] ≥ [Entry + $ Target]. Короткие сделки: покупка при закрытии размещается, если Close [i] ≤ [Entry — $ Target]. i ~ Текущий бар. $ Target — это значение, кратное начальному риску на сделку (определяется выходами) и Target_Index.
Быстрый выход: длинных сделок: стоп-ордер на продажу размещается на один тик ниже минимума (минимум [k — 1], минимум [k]). Короткие сделки: стоп-ордер на покупку размещается на один тик выше максимума (High [k — 1], High [k]). Индекс: k ~ Панель входа.
Stop Loss Exit: ATR (ATR_Length) — средний истинный диапазон за период ATR_Length. ATR_Stop кратно ATR (ATR_Length). Длинные сделки: стоп-ордер на продажу размещается на [Вход — ATR (ATR_Length) * ATR_Stop]. Короткие сделки: стоп-ордер на покупку размещается на [Вход + ATR (ATR_Length) * ATR_Stop].
Time_Index = [1, 40], шаг = 1;
Target_Index = [1.0, 10.0], шаг = 0,25;
ATR_Length = 20;
ATR_Stop = 6;
Тест чувствительности: Time_Index = [1, 40], Step = 1
Target_Index = [1.0, 10.0], Шаг = 0,25
Размер позиции: Initial_Capital = 1000000 долларов США
Fixed_Fractional = 1%
Портфель = 42 фьючерса США
ATR_Stop = 6 (ATR ~ Средний истинный диапазон)
ATR_Length = 90_Length

Данные: 42 фьючерсных рынка; 32 года (01.01.2011 — 31.12.2011)