Контекстный класс в шаблоне Стратегии

10

Я пытаюсь понять шаблон стратегии и спрашиваю себя: должен ли быть контекстный класс или я могу оставить его без компромисса с целью шаблона?

У меня сложилось впечатление, что мне нужен какой-то переключатель для чтения разных типов файлов, но я не хотел просто что-то взламывать, а потом заниматься рефакторингом (хотя, конечно, всегда бывает, что код можно реорганизовать, но идея была в следующем: try быть максимально умным в дизайне заранее ...)

введите описание изображения здесь

Изображение взято из Викимедиа

Может ли клиент делегировать напрямую интерфейсу Стратегии, или я что-то упустил, чтобы понять о классе контекста?

interface Reader {
    // read information from file and fill data list field of Client
    readFile();
}
class ExcelReader implements Reader{ /* */ }
class PdfReader implements Reader{ /* */}

class Client{
    // strategic choice
    Reader r;

    // data list field
    List<Data> data;

    // Client Constructor
    public Client(){
        if(<file ends in .xls>)
            r = new ExcelReader();
        else
            r = new PdfReader();
        r.readFile();
    }
}

Итак, на рисунке выше отсутствует контекстный класс. Код придерживается шаблона стратегии?

Panny
источник
1
В качестве еще одного интересного / важного момента я хотел бы обратить ваше внимание на то, что концепция классов типов в функциональных языках - это «просто» шаблон стратегии с видами en.wikipedia.org/wiki/Kind_(type_theory) ). Оба являются всего лишь механизмом реализации для специального полиморфизма.
AndreasScheinert
Связано ли это (в значительной степени или менее) с Java 8 Project Lambda? Статья в Википедии слишком плотная, чтобы я ее сразу понял, но если это часть теоретического фона для эффективного использования новых возможностей Java (или программирования в целом), я с радостью потрачу на это больше времени.
Панни
1
Очень далеко, но я бы сказал, да, классы типа нужны. Язык программирования, который поддерживает высшие виды. Это было бы в случае Скала и Хаскелла. Суть в том, что (ad hoc) полиморфизм реализован по-другому, и если вы сделаете шаг назад, вы сможете узнать немного о полиморфизме в целом.
AndreasScheinert

Ответы:

13

В вашем примере вызов кода readFileявляется частью конструктора Client. Этот метод является "контекстом", который вы ищете . Шаблон стратегии не нуждается буквально в «классе контекста», и в первой версии вашего кода объект стратегии (в вашем случае «Reader») может находиться только в локальной переменной. Особенно, когда нужно вызвать только один «стратегический метод» («readFile»).

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

Док Браун
источник
5

Безусловно. Шаблоны - это просто рекомендации. Вам все равно нужно будет адаптировать и правильно применять их для решения проблемы. Лично я редко позволяю устанавливать стратегию во время выполнения; чаще это указывается на стройке или раскручивается на фабрике.

Хотя можно также утверждать, что setStrategyэто личное, и моя инъекция просто использует шаблон, как показано.

Telastyn
источник
Означает ли это, что изображенный класс Context может быть оставлен без ущерба для шаблона? Или, другими словами, это нормально, когда мой клиентский класс является изображенным классом контекста?
Панни
6
@panny - я не решаюсь ответить на вопрос, потому что это указывает на то, что вы упустили суть ответа, и на самом деле шаблоны вообще. Шаблон стратегии позволяет варьировать поведение, предоставляя различные конкретные реализации интерфейса. Это концепция , а не формула .
Теластин