Статьи

Пример шаблона дизайна стратегии

Эта статья является частью нашего курса Академии под названием « Шаблоны проектирования Java» .

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

1. Введение

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

Чтобы понять шаблон проектирования стратегии, давайте создадим форматировщик текста для текстового редактора. Каждый должен знать о текстовом редакторе. Текстовый редактор может иметь разные форматеры текста для форматирования текста. Мы можем создать различные форматеры текста и затем передать необходимый текстовый редактор, чтобы редактор мог форматировать текст по мере необходимости.

Текстовый редактор будет содержать ссылку на общий интерфейс для средства форматирования текста, и работа редактора будет состоять в том, чтобы передавать текст в средство форматирования для форматирования текста.

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

2. Что такое шаблон стратегии

Шаблон разработки стратегии определяет семейство алгоритмов, инкапсулируя каждый из них и делая их взаимозаменяемыми. Стратегия позволяет алгоритму варьироваться независимо от клиентов, которые его используют.

Шаблон Стратегия полезен, когда существует набор связанных алгоритмов, и клиентский объект должен иметь возможность динамически выбирать и выбирать алгоритм из этого набора, который соответствует его текущей потребности. Шаблон «Стратегия» предполагает хранение реализации каждого из алгоритмов в отдельном классе. Каждый такой алгоритм, заключенный в отдельный класс, называется strategy . Объект, который использует объект Strategy часто называют объектом context .

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

Когда группа связанных алгоритмов инкапсулирована в набор классов Strategy в иерархии классов, клиент может выбрать один из этих алгоритмов, выбрав и создав соответствующий экземпляр класса Strategy . Чтобы изменить поведение context , клиентский объект должен сконфигурировать context с выбранным экземпляром strategy . Этот тип компоновки полностью отделяет реализацию алгоритма от context который его использует. В результате при изменении реализации существующего алгоритма или добавлении нового алгоритма в группу и context и объект клиента (который использует context ) остаются неизменными.

Рисунок 1 - Диаграмма классов стратегии

Рисунок 1 — Диаграмма классов стратегии

стратегия

  • Объявляет интерфейс, общий для всех поддерживаемых алгоритмов. Context использует этот интерфейс для вызова алгоритма, определенного ConcreteStrategy .

ConcreteStrategy

  • Реализует алгоритм с использованием интерфейса Strategy .

контекст

  • Настраивается с помощью объекта ConcreteStrategy .
  • Поддерживает ссылку на объект Strategy .
  • Может определять интерфейс, который позволяет Strategy получать доступ к своим данным.

3. Реализация шаблона проектирования стратегии

Ниже представлен интерфейс TextFormatter реализованный всеми конкретными форматтерами.

1
2
3
4
5
6
7
package com.javacodegeeks.patterns.strategypattern;
 
public interface TextFormatter {
     
    public void format(String text);
 
}

Вышеуказанный интерфейс содержит только один метод format , используемый для форматирования текста.

01
02
03
04
05
06
07
08
09
10
package com.javacodegeeks.patterns.strategypattern;
 
public class CapTextFormatter implements TextFormatter{
 
    @Override
    public void format(String text) {
        System.out.println("[CapTextFormatter]: "+text.toUpperCase());
    }
 
}

Приведенный выше класс CapTextFormatter представляет собой конкретный форматировщик текста, который реализует интерфейс TextFormatter и этот класс используется для преобразования текста в прописные буквы.

01
02
03
04
05
06
07
08
09
10
package com.javacodegeeks.patterns.strategypattern;
 
public class LowerTextFormatter implements TextFormatter{
 
    @Override
    public void format(String text) {
        System.out.println("[LowerTextFormatter]: "+text.toLowerCase());
    }
 
}

LowerTextFormatter — это конкретный форматировщик текста, который реализует интерфейс TextFormatter а класс используется для преобразования текста в маленький регистр.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
package com.javacodegeeks.patterns.strategypattern;
 
public class TextEditor {
     
    private final TextFormatter textFormatter;
     
    public TextEditor(TextFormatter textFormatter){
        this.textFormatter = textFormatter;
    }
     
    public void publishText(String text){
        textFormatter.format(text);
    }
 
}

Приведенный выше класс является классом TextEditor который содержит ссылку на интерфейс TextFormatter . Класс содержит метод publishText который направляет текст в publishText форматирования, чтобы опубликовать текст в нужном формате.

Теперь давайте проверим код выше.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
package com.javacodegeeks.patterns.strategypattern;
 
public class TestStrategyPattern {
 
    public static void main(String[] args) {
        TextFormatter formatter = new CapTextFormatter();
        TextEditor editor = new TextEditor(formatter);
        editor.publishText("Testing text in caps formatter");
         
        formatter = new LowerTextFormatter();
        editor = new TextEditor(formatter);
        editor.publishText("Testing text in lower formatter");
 
    }
 
}

Приведенный выше код приведет к следующему выводу:

1
2
[CapTextFormatter]: TESTING TEXT IN CAPS FORMATTER
[LowerTextFormatter]: testing text in lower formatter

В приведенном выше классе мы сначала создали CapTextFormatter и присвоили его экземпляру TextEditor . Затем мы publishText метод publishText и передали ему некоторый входной текст.

Опять же, мы сделали то же самое, но на этот раз LowerTextFormatter передается в TextEditor .

Вывод ясно показывает различный формат текста, созданный различными текстовыми редакторами из-за различного форматера текста, используемого им.

Основным преимуществом паттерна разработки стратегии является то, что мы можем улучшить код без особых проблем. Мы можем добавлять новые средства форматирования текста, не нарушая текущий код. Это сделало бы наш код обслуживаемым и гибким. Этот шаблон проектирования также поддерживает принцип дизайна «код для интерфейса».

4. Когда использовать шаблон проектирования стратегии

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

  • Многие связанные классы отличаются только своим поведением. Стратегии предоставляют способ настроить класс с одним из многих поведений.
  • Вам нужны разные варианты алгоритма. Например, вы можете определить алгоритмы, отражающие различные компромиссы пространства / времени. Стратегии могут использоваться, когда эти варианты реализованы в виде иерархии классов алгоритмов.
  • Алгоритм использует данные, о которых клиенты не должны знать. Используйте шаблон «Стратегия», чтобы избежать раскрытия сложных, специфичных для алгоритма структур данных.
  • Класс определяет много поведений, и они появляются как несколько условных операторов в своих операциях. Вместо многих условных выражений перенесите соответствующие условные ветви в свой собственный класс Strategy .

5. Шаблон стратегии в JDK

  • java.util.Comparator#compare()
  • javax.servlet.http.HttpServlet
  • javax.servlet.Filter#doFilter()

6. Загрузите исходный код

Это был урок по шаблону разработки стратегии. Вы можете скачать исходный код здесь: StrategyPattern-Project