Рассмотрим такой поведенческий шаблон проектирования, как Стратегия (Strategy). Также будет приведен пример реализации шаблона стратегия в рамках программы, работающей со строками. Разработку будем вести на языке программирования C#.
Паттерн Стратегия
Стратегия (англ. Strategy) — это шаблон проектирования (паттерн), относящийся к классу поведенческих и предназначенный, прежде всего, для использования в таких случаях, когда в решаемой задаче в каком-то определенном месте необходимо использовать различные алгоритмы в зависимости от конкретного состояния системы и/или ее окружения в конкретный момент времени. При этом, когда используется паттерн Стратегия, появляется возможность изменять алгоритм, решающий задачу, независимо от объектов-клиентов, которые его используют.
Ниже мы проиллюстрируем данное определение шаблона проектирования Стратегия примером задачи и программы, которая ее решает. А пока приведем классовую диаграмму для шаблона проектирования в нотации UML:
Шаблон Стратегия, согласно данной диаграммы, реализуется следующим образом (язык C#):
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 |
using System; namespace Strategy { //Этот интерфейс, должен наследовать класс, реализующий конкреную стратегию //Класс Context использует данный интерфейс для вызова конкретной стратегии public interface IStrategy { void Algorithm(); } //Первая конкретная реализация-стратегия public class ConcreteStrategy1 : IStrategy { public void Algorithm() { Console.WriteLine("Выполняется алгоритм стратегии номер ОДИН."); } } //Вторая конкретная реализация-стратегия //Реализаций стратегий (различных алгоритмов) может быть сколько угодно. Столько //сколько требуется для решения конкретной задачи public class ConcreteStrategy2 : IStrategy { public void Algorithm() { Console.WriteLine("Выполняется алгоритм стратегии номер ДВА."); } } //Контекст, использующий стратегию для решения поставленной задачи public class Context { //Ссылка на интерфейс IStrategy //используется при переключении между конкретными реализациями //(проще говоря, это выбор конкретной стратегии) private IStrategy _strategy; //Конструктор контекста //Инициализирует объект контекста заданной стратегией public Context(IStrategy strategy) { _strategy = strategy; } //Метод для установки стратегии //Используется для смены стратегии во время выполнения программы public void SetStrategy(IStrategy strategy) { _strategy = strategy; } //Запускает выполнение алгоритма выбранной стратегии public void ExecuteOperation() { _strategy.Algorithm(); } } //Класс программы public static class Program { public static void Main() { //Создаем контекст и инициализируем его первой стратегией Context context = new Context(new ConcreteStrategy1()); //Выполняем операцию (алгоритм) первой стратегии context.ExecuteOperation(); //Заменяем в context первую стратегию на вторую context.SetStrategy(new ConcreteStrategy2()); //Выполняем операцию (алгоритм) теперь уже второй стратегии context.ExecuteOperation(); } } } |
В результате выполнения программы в консоль будет выведено:
Выполняется алгоритм стратегии номер ОДИН.
Выполняется алгоритм стратегии номер ДВА.
Пример задачи, решаемой шаблоном Стратегия
Задание. Реализовать программный продукт, выполняющий проверку введенной пользователем строки — что введено (да или нет): число, строка в нижнем регистре или строка в верхнем регистре? При разработке использовать поведенческий шаблон проектирования «Стратегия».
Решение. Создадим следующий интерфейс для программы на Windows Forms:
Исходный код программы на языке программирования C# приводим далее.
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace ASP_lr3 { public partial class Form1 : Form { Context context; public Form1() { InitializeComponent(); context = new Context(new ConcreteStrategy1()); } private void check_Button_Click(object sender, EventArgs e) { if(number_radioButton.Checked) context.SetStrategy(new ConcreteStrategy1()); else if (lower_radioButton.Checked) context.SetStrategy(new ConcreteStrategy2()); else context.SetStrategy(new ConcreteStrategy3()); context.ExecuteOperation(input_TextBox.Text); } } public interface IStrategy { void Algorithm(string s); } //Первая конкретная реализация-стратегия public class ConcreteStrategy1 : IStrategy { public void Algorithm(string s) { if (s.Length == 0) MessageBox.Show("Строка пуста"); else { foreach(char c in s) { if (!(c >= '0' && c <= '9')) { MessageBox.Show("Введенная строка - НЕ число!!!"); return; } } MessageBox.Show("Верно"); } } } //Вторая конкретная реализация-стратегия public class ConcreteStrategy2 : IStrategy { public void Algorithm(string s) { if (s.Length == 0) MessageBox.Show("Строка пуста"); else { foreach (char c in s) { if (!(c >= 'а' && c <= 'я' || c == 'ё' || c >= 'a' && c <= 'z')) { MessageBox.Show("Введенная строка НЕ в нижнем регистре!!!"); return; } } MessageBox.Show("Верно"); } } } //Третья конкретная реализация-стратегия public class ConcreteStrategy3 : IStrategy { public void Algorithm(string s) { if (s.Length == 0) MessageBox.Show("Строка пуста"); else { foreach (char c in s) { if (!(c >= 'А' && c <= 'Я' || c == 'Ё' || c >= 'A' && c <= 'Z')) { MessageBox.Show("Введенная строка НЕ в верхнем регистре!!!"); return; } } MessageBox.Show("Верно"); } } } public class Context { private IStrategy _strategy; public Context(IStrategy strategy) { _strategy = strategy; } public void SetStrategy(IStrategy strategy) { _strategy = strategy; } public void ExecuteOperation(string s) { _strategy.Algorithm(s); } } } |
Демонстрация работы программы, решающей поставленную задачу и реализующей шаблон проектирования Стратегия:
Классовая диаграмма написанной программы выглядит следующим образом:
Скачать исходник программы из данного урока (для Visual Studio), можно, нажав на кнопку:
Скачать исходник
Достоинства и недостатки шаблона
Достоинства паттерна Стратегия:
- Программу легче поддерживать и модифицировать, потому что весь набор алгоритмов расположен в обособленной иерархии классов
- Шаблон Стратегия позволяет менять один алгоритм на другой во время исполнения программы («на лету»)
- Данный шаблон скрывает подробности реализации алгоритмов от клиентов
Недостатки паттерна Стратегия:
- Для корректной настройки программы ее пользователь должен знать об особенностях реализации всех алгоритмов
- Количество классов в коде программного продукта, разработанного с помощью шаблона Стратегия, безусловно, возрастает
Поделиться в соц. сетях: