Шаблон Strategy

Делегаты представляют собой удобный механизм для реализации шаблона Strategy (Стратегия). В основе своей шаблон Strategy позволяет динамически заменять вычислительные алгоритмы в зависимости от ситуации, сложившейся во время выполнения.

Например, рассмотрим распространенный случай сортировки группы элементов. Предположим, что требуется максимально быстрое выполнение сортировки.

Из-за особенностей системы обеспечение желаемой скорости связано с большим расходом памяти для временного хранения элементов.

Это отлично подходит для коллекций относительно управляемого размера, но если коллекция разрастается до громадных размеров, может случиться, что объем памяти, необходимый для проведения быстрой сортировки, превысит емкость системных ресурсов.

Для таких случаев можно предусмотреть алгоритм сортировки, который работает медленнее, но зато потребляет намного меньше системных ресурсов. позволяет заменять эти алгоритмы во время выполнения, в зависимости от конкретных условий. Этот пример, несмотря на свою надуманность, отлично иллюстрирует предназначение данного шаблона.

Обычно шаблон Strategy реализуется с помощью интерфейсов. Сначала объявляется интерфейс, который реализуют все стратегии. После этого потребитель алгоритма может не беспокоиться о том, какая именно реализация стратегии будет использована.

Делегаты являются легковесной альтернативой применению интерфейсов для реализации простой стратегии. Интерфейсы — это просто механизм для реализации программного контракта. Предположим, что объявление делегата используется для реализации контракта, а любой метод, соответствующий сигнатуре делегата, представляет собой конкретную стратегию. Теперь вместо хранения ссылки на абстрактный интерфейс стратегии потребитель просто хранит экземпляр делегата.

Описанный сценарий иллюстрируется в следующем примере:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
using System;
using System.Collections;
public delegate Array SortStrategy( ICollection theCollection );
public class Consumer
{
public Consumer( SortStrategy defaultStrategy )  {
this.strategy = defaultStrategy;
private SortStrategy strategy;
public SortStrategy Strategy {
get {
return strategy;  }
set {
strategy = value;  }
}
public void DoSomeWork ()  {
// Использовать стратегию.
Array sorted = strategy( myCollection );
// Сделать что-то с результатом.
}
private ArrayList myCollection;
}
public class SortAlgorithms {
static Array SortFast ( ICollection theCollection )  {
// Выполнить быструю сортировку.
}
static Array SortSlow( ICollection theCollection )  {
// Выполнить медленную сортировку.
}

После создания экземпляр объекта Consumer получает стратегию сортировки по умолчанию, которая представляет собой не что иное, как метод, реализующий сигнатуру делегата SortStrategy. В зависимости от условий, сложившихся во время выполнения, экземпляру Consumer предоставляется соответствующий делегат, и метод Consumer.DoSomeWork автоматически вызовет требуемую стратегию.

С помощью свойства SortStrategy используемую стратегию можно даже изменять во время выполнения. Показанная реализация шаблона Strategy оказывается даже еще более гибкой, чем применение интерфейсов, поскольку делегаты могут привязываться как к статическим методам, так и к методам экземпляра.

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

Вы можете следить за любыми ответами на эту запись через RSS 2.0 ленту. Вы можете оставить ответ, или trackback с вашего собственного сайта.

Оставьте отзыв

XHTML: Вы можете использовать следующие теги: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

 
Rambler's Top100