Паттерн Стратегия (Strategy) в Java

Паттерн Стратегия (Strategy) относится к поведенческим (behavioral) паттернам проектирования. Также известен как Политика (Policy).

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

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

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

Пример паттерна Стратегия на Java

Предположим, что у нас есть класс Computer, он умеет выполнять задание - метод runTask:

public class Computer {
    private ComputerStrategy strategy;

    public Computer(ComputerStrategy strategy){
        this.strategy = strategy;
    }

    public void setNewTask(ComputerStrategy strategy){
        this.strategy = strategy;
    }

    public void runTask() {
        this.strategy.execute();
    }
}

Computer может выполнять много разных алгоритмов-заданий - они приходят к нему через контруктор либо через метод setNewTask. Вот примеры алгоритмов-заданий:

import java.util.logging.Logger;

public class Video implements ComputerStrategy {
    private static final Logger LOGGER = Logger.getLogger(Video.class.getName());

    @Override
    public void execute() {
        LOGGER.info("Video playing");
    }
}

import java.util.logging.Logger;

public class Music implements ComputerStrategy {
    private static final Logger LOGGER = Logger.getLogger(Music.class.getName());

    @Override
    public void execute() {
        LOGGER.info("Music playing");
    }
}

import java.util.logging.Logger;

public class Game implements ComputerStrategy {
    private static final Logger LOGGER = Logger.getLogger(Game.class.getName());

    @Override
    public void execute() {
        LOGGER.info("Gaming now");
    }
}

Каждый из этих алгоритмов реализует интерфейс ComputerStrategy:

@FunctionalInterface
public interface ComputerStrategy {
    void execute();
}

За счет аннотации @FunctionalInterface классу Computer кроме заранее заданных стратегий можно передавать из определяемые функиональным образом, такие как например
() -> LOGGER.info("Write program"):

import java.util.logging.Logger;

public class App {
    private static final Logger LOGGER = Logger.getLogger(App.class.getName());

    public static void main(String[] args){
        LOGGER.info("Switch on computer and play movie");
        Computer computer = new Computer(new Video());
        computer.runTask();

        LOGGER.info("Find music");
        computer.setNewTask(new Music());
        computer.runTask();

        LOGGER.info("Find game");
        computer.setNewTask(new Game());
        computer.runTask();

        // Java 8
        Computer functionalComputer = new Computer(
                () -> LOGGER.info("Write program")
        );
        functionalComputer.runTask();

        functionalComputer = new Computer(
                () -> LOGGER.info("Execute some code and get some output")
        );
        functionalComputer.runTask();
    }
}


Читайте также:


Комментарии

Популярные сообщения из этого блога

Методы класса Object в Java

Как получить текущий timestamp в Java

Основные опции JVM для повышения производительности и отладки