Стратегия (шаблон проектирования)

Материал из Seo Wiki - Поисковая Оптимизация и Программирование

Перейти к: навигация, поиск
Название Стратегия
Английское название Strategy
Диаграмма
Тип поведенческий
Назначение позволяет использовать различные бизнес-правила или алгоритмы в зависимости от контекста.
Применяется в случаях в одном и том же случае, в зависимости от текущего состояния системы или её окружения, используются различные алгоритмы.
Плюсы  
  • инкапсуляция реализации различных алгоритмов, система становится независимой от возможных изменений бизнес-правил;
  • вызов всех алгоритмов одним стандартным образом;
  • отказ от использования переключателей и/или условных операторов.
Минусы создание дополнительных классов
Родственные шаблоны Мост, Шаблонный метод, Адаптер

Стратегия, Strategy — поведенческий шаблон проектирования, предназначенный для определения семейства алгоритмов, инкапсуляции каждого из них и обеспечения их взаимозаменяемости. Это позволяет выбирать алгоритм путем определения соответствующего класса. Шаблон Strategy позволяет менять выбранный алгоритм независимо от объектов-клиентов, которые его используют.

Содержание

[править] Основные характеристики

[править] Задача

Выбор алгоритма, который следует применить, в зависимости от типа выдавшего запрос клиента или обрабатываемых данных. Если используется правило, которое не подвержено изменениям, нет необходимости обращаться к шаблону «стратегия».

[править] Мотивы

  • Программа должна обеспечивать различные варианты алгоритма или поведения
  • Нужно изменять поведение каждого экземпляра класса
  • Необходимо изменять поведение объектов на стадии выполнения
  • Введение интерфейса позволяет классам-клиентам ничего не знать о классах, реализующих этот интерфейс и инкапсулирующих в себе конкретные алгоритмы

[править] Способ решения

Отделение процедуры выбора алгоритма от его реализации. Это позволяет сделать выбор на основании контекста.

[править] Участники

  • Класс Strategy определяет как будут использоваться различные алгоритмы.
  • Конкретные классы ConcreteStrategy реализуют эти различные алгоритмы.
  • Класс Context использует конкретные классы ConcreteStrategy посредством ссылки на конкретный тип абстрактного класса Strategy. Классы Strategy и Context взаимодействуют с целью реализации выбранного алгоритма (в некоторых случаях классу Strategy требуется посылать запросы классу Context). Класс Context пересылает классу Strategy запрос, поступивший от его класса-клиента.

[править] Следствия

  • Шаблон Strategy определяет семейство алгоритмов.
  • Это позволяет отказаться от использования переключателей и/или условных операторов.
  • Вызов всех алгоритмов должен осуществляться стандартным образом (все они должны иметь одинаковый интерфейс).

[править] Реализация

Класс, который использует алгоритм (Context), включает абстрактный класс (Strategy), обладающий абстрактным методом, определяющим способ вызова алгоритма. Каждый производный класс реализует один требуемый вариант алгоритма.

Замечание: метод вызова алгоритма не должен быть абстрактным, если требуется реализовать некоторое поведение, принимаемое по умолчанию.

[править] Примеры

[править] Пример на C#

using System;
 
namespace DesignPatterns.Behavioral.Strategy
{
    /// <summary>
    /// Интерфейс «Стратегия» определяет функциональность (в данном примере это метод
    /// <see cref="Algorithm">Algorithm</see>), которая должна быть реализована
    /// конкретными классами стратегий. Другими словами, метод интерфейса определяет
    /// решение некой задачи, а его реализации в конкретных классах стратегий определяют,
    /// КАК, КАКИМ ПУТЁМ эта задача будет решена.
    /// </summary>
    public interface IStrategy
    {
        void Algorithm();
    }
 
    /// <summary>
    /// Первая конкретная реализация-стратегия.
    /// </summary>
    public class ConcreteStrategy1 : IStrategy
    {
        public void Algorithm()
        {
            Console.WriteLine("Выполняется алгоритм стратегии 1.");
        }
    }
 
    /// <summary>
    /// Вторая конкретная реализация-стратегия.
    /// Реализаций может быть сколько угодно много.
    /// </summary>
    public class ConcreteStrategy2 : IStrategy
    {
        public void Algorithm()
        {
            Console.WriteLine("Выполняется алгоритм стратегии 2.");
        }
    }
 
    /// <summary>
    /// Контекст, использующий стратегию для решения своей задачи.
    /// </summary>
    public class Context
    {
        /// <summary>
        /// Ссылка на интерфейс <see cref="IStrategy">IStrategy</see>
        /// позволяет автоматически переключаться между конкретными реализациями
        /// (другими словами, это выбор конкретной стратегии).
        /// </summary>
        private IStrategy _strategy;
 
        /// <summary>
        /// Конструктор контекста.
        /// Инициализирует объект стратегией.
        /// </summary>
        /// <param name="strategy">
        /// Стратегия.
        /// </param>
        public Context(IStrategy strategy)
        {
            _strategy = strategy;
        }
 
        /// <summary>
        /// Метод для установки стратегии.
        /// Служит для смены стратегии во время выполнения.
        /// В C# может быть реализован также как свойство записи.
        /// </summary>
        /// <param name="strategy">
        /// Новая стратегия.
        /// </param>
        public void SetStrategy(IStrategy strategy)
        {
            _strategy = strategy;
        }
 
        /// <summary>
        /// Некоторая функциональность контекста, которая выбирает
        /// стратегию и использует её для решения своей задачи.
        /// </summary>
        public void ExecuteOperation()
        {
            _strategy.Algorithm();
        }
    }
 
    /// <summary>
    /// Класс приложения.
    /// В данном примере выступает как клиент контекста.
    /// </summary>
    public static class Program
    {
        /// <summary>
        /// Точка входа в программу.
        /// </summary>
        public static void Main()
        {
            // Создём контекст и инициализируем его первой стратегией.
            Context context = new Context(new ConcreteStrategy1());
            // Выполняем операцию контекста, которая использует первую стратегию.
            context.ExecuteOperation();
            // Заменяем в контексте первую стратегию второй.
            context.SetStrategy(new ConcreteStrategy2());
            // Выполняем операцию контекста, которая теперь использует вторую стратегию.
            context.ExecuteOperation();
        }
    }
}

[править] Примеры на Javascript

// "интерфейс" Strategy
 
	function Strategy() {
		this.exec = function() {};
	};
 
 
// реализации Strategy
 
	// показ ссобщения в статусной строке браузера
	// (поддерживается не всеми браузерами)
	function StrategyWindowStatus() {
		this.exec = function(message) {
			window.status = message;
		};
	};
	StrategyWindowStatus.prototype = new Strategy();
	StrategyWindowStatus.prototype.constructor = StrategyWindowStatus;
 
	// показ сообщения с помощью попапа
	// (может быть заблокировано браузером)
	function StrategyNewWindow() {
		this.exec = function(message) {
			var win = window.open("", "_blank");
			win.document.write("<html>"+ message +"</html>");
		};
	};
	StrategyNewWindow.prototype = new Strategy();
	StrategyNewWindow.prototype.constructor = StrategyNewWindow;
 
	// показ сообщения с помощью модального окна
	function StrategyAlert() {
		this.exec = function(message) {
			alert(message);
		};
	};
	StrategyAlert.prototype = new Strategy();
	StrategyAlert.prototype.constructor = StrategyAlert;
 
 
// Context
 
	function Context(strategy) {
		this.exec = function(message) {
			strategy.exec(message);
		};
	}
 
 
// Использование
 
var showInWindowStatus = new Context( new StrategyWindowStatus() );
var showInNewWindow = new Context( new StrategyNewWindow() );
var showInAlert = new Context( new StrategyAlert() );
 
showInWindowStatus.exec("сообщение");
showInNewWindow.exec("сообщение");
showInAlert.exec("сообщение");
[править] Пример с использованием динамических (first-class) функций
function Context(fn) {
	this.exec = function() {
		fn.apply(this, arguments || []);
	};
};
 
var showInWindowStatus = new Context( function(message) {
	window.status = message;
} );
var showInNewWindow = new Context( function(message) {
	var win = window.open("", "_blank");
	win.document.write("<html>"+ message +"</html>");
} );
var showInAlert = new Context( function(message) {
	alert(message);
} );
 
showInWindowStatus.exec("сообщение");
showInNewWindow.exec("сообщение");
showInAlert.exec("сообщение");

[править] Примеры на PHP5

abstract class FileNamingStrategy{
	abstract function createLinkName($filename);
}
 
class ZipFileNamingStrategy extends FileNamingStrategy{
	function createLinkName($filename){
	return "http://downloads.foo.bar/$filename.zip";
	}
}
 
class TarGzFileNamingStrategy extends FileNamingStrategy{
	function createLinkName($filename){
	return "http://downloads.foo.bar/$filename.tar.gz";
	}
}
 
if(strstr($_SERVER["HTTP_USER_AGENT"], "Win")){
$fileNamingObj = new ZipFileNamingStrategy();
}
else {
$fileNamingObj = new TarGzFileNamingStrategy();
}
 
$calc_filename = $fileNamingObj->createLinkName("Calc101");
$stat_filename = $fileNamingObj->createLinkName("Stat2000");
 
print <<<EOF
<h1>The following is a list of great downloads</h1><br />
<a href="$calc_filename">A great calculator</a><br />
<a href="$stat_filename">The best statistics application</a>
EOF;

[править] Источники информации

  • Шаллоуей, Алан, Тротт, Джейм, Р. Шаблоны проектирования. Новый подход к объектно-ориентированному анализу и проектированию: Пер. с англ. —М.: Издательский дом «Вильямс», 2002. —288 с. ISBN 5-8459-0301-7
  • Grand, Mark. Шаблоны проектирования в Java: Пер. с англ. — М.: Новое знание, 2004. — 559 с. ISBN 5-94735-047-5


bg:Стратегия (шаблон)

ca:Patró estratègia cs:Strategy de:Strategie (Entwurfsmuster) en:Strategy pattern es:Strategy (patrón de diseño) fr:Stratégie (patron de conception) it:Strategy pattern ja:Strategy パターン pl:Strategia (wzorzec projektowy) pt:Strategy vi:Strategy pattern zh:策略模式


Served in 0.815 secs.