Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Шаблоны проектирования.pdf
Скачиваний:
75
Добавлен:
11.05.2015
Размер:
1.13 Mб
Скачать

4.8. Стратегия (Strategy)

При помощи шаблона Стратегия из клиента выделяется алгоритм, который затем инкапсулируется в типах, наследуемых от общего класса (реализующих общий интерфейс). Это позволяет клиенту выбирать нужный алгоритм путём создания объектов необходимых типов. Кроме этого, шаблон допускает изменение набора доступных алгоритмов со временем.

Client

 

 

StrategyBase

 

 

 

 

+Strategy:StrategyBase

 

 

 

 

 

 

 

+CallAlgorithm()

 

 

+Algorithm()

 

 

 

 

StrategyA StrategyB

+Algorithm() +Algorithm()

Рис. 17. Диаграмма шаблона Стратегия.

Предположим, что требуется разработать программу, которая показывает календарь. Одно из требований к программе – она должна отображать праздники, отмечаемые различными нациями и религиозными группами. Это требование можно выполнить, помещая логику генерирования каждого набора праздников в отдельный класс. Основная программа будет выбирать необходимый класс из набора, исходя, например, из действий пользователя (или конфигурационных настроек). Ниже приведён пример кода, реализующий поставленную задачу при помощи шаблона Стратегия.

using System.Collections.Generic;

public interface IHolidaySet

{

List<string> GetHolidays();

}

public class USAHolidays : IHolidaySet

{

public List<string> GetHolidays()

{

return new List<string>

{

"01.01.13", "21.01.13", "18.02.13", "27.05.13", "04.07.13", "02.09.13", "14.10.13",

53

"11.11.13", "28.11.13", "25.12.13"

};

}

}

public class RussiaHolidays : IHolidaySet

{

public List<string> GetHolidays()

{

return new List<string>

{

"01.01.13", "07.01.13", "23.02.13", "08.03.13", "11.03.13", "01.05.13", "09.05.13", "12.06.13", "04.11.13"

};

}

}

public class Client

{

private readonly IHolidaySet _holidaySetStrategy;

public Client(IHolidaySet strategy)

{

_holidaySetStrategy = strategy;

}

public bool CheckForHoliday(string date)

{

return _holidaySetStrategy.GetHolidays().Contains(date);

}

}

public class StrategyExample

{

public static void Main()

{

var client = new Client(new USAHolidays());

var result = client.CheckForHoliday("04.07.13");

}

}

54

4.9. Цепочка обязанностей (Chain of responsibility)

Шаблон Цепочка обязанностей работает со списком объектов, называемых обработчиками. Каждый из обработчиков имеет естественные ограничения на множество запросов, которые он в состоянии поддержать. Если текущий обработчик не может поддержать запрос, он передаёт его следующему обработчику в списке. Так продолжается, пока запрос не будет обработан, или пока список не закончится.

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

HandlerBase

HandleRequest() вызывает

 

+Successor:HandlerBase

Successor.HandleRequest(),

+HandleRequest()

если необходимо

 

HandlerA

HandlerB

+HandleRequest()

+HandleRequest()

Рис. 18. Диаграмма шаблона Цепочка обязанностей.

Ниже приведён код, иллюстрирующий применение шаблона Цепочка обязанностей.

public class Handler

{

public int Limit { get; private set; } public Handler Next { get; private set; }

public Handler(int limit, Handler handler)

{

Limit = limit; Next = handler;

}

public string HandleRequest(int data)

{

if (data < Limit)

{

return string.Format("Request for {0} handled", data);

}

if (Next != null)

{

return Next.HandleRequest(data);

}

55

return "Request handled BY DEFAULT";

}

}

public class ChainOfResponsibilityExample

{

public static void Main()

{

Handler start = null;

for (var i = 5; i > 0; i--)

{

start = new Handler(i*1000, start);

}

int[] data = {50, 2000, 1500, 10000, 175, 4500}; foreach (var i in data)

{

System.Console.WriteLine(start.HandleRequest(i));

}

}

}

4.10. Шаблонный метод (Template method)

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

Вкачестве иллюстрации применения шаблонного метода рассмотрим класс

сметодом сортировки. Пусть этот метод вызывает отдельный метод сравнения элементов сортируемого набора. Классы-наследники переопределяют метод

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

using System;

public abstract class Sorter

{

private readonly int[] data;

protected Sorter(params int[] source)

{

data = new int[source.Length]; Array.Copy(source, data, source.Length);

}

protected abstract bool Compare(int x, int y);

56