Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Сергей Гурин!
А>В общем мысль неплохая, но есть противоречия и неудобства: А>Противоречие: А> Вы писали что А>"Для расширения или изменения функциональности создавайте новый класс команды, оставляя существующий класс без изменений. Старые программы (или фрагменты программ) смогут при этом работать без изменений, а новые программы будут использовать расширенные возможности." А> Но при добавлении нового класса будет изменен интерфейс IContext, который также как и класс Command опубликован и соответсвенно изменение его не желательно, так как влечет изменение всех получателей. А> Неудобства: А> Все получатели должны знать все команды, А>Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы и др. "Приемы объектно-ориентированного проектирования",написать какого то конкретного получателя под конкрентную задачу.
Ответ от автора.
IContext в принципе не может оставаться стабильным при расширении набора команд. Но получатель будет распознавать (создавать с помощью фабрики классов) только те команды, которые были заложены при его разработке. То есть, совершенно не нужно переделывать старых получателей при появлении новых команд (конечно, если получатели реализованы в отдельных exe или dll-файлах). Но при эволюции старого получателя и его перекомпиляции, действительно приходится добавлять весь набор новых команд. Это естественная плата за контроль типов команд на этапе компиляции и за единственность декларации. Если получателю команда не нужна, то ее можно сделать в виде заглушки при реализации IReceiver и не регистрировать команду для фабрики классов (чтобы она вообще никогда не создавалась у данного получателя). Можно несколько сгладить обсуждаемый недостаток, если воспользоваться средствами макрообработки (директивами #ifdef в Си++ или {$IFDEF} в Delphi) разрешая включение в код групп команд и соответствующих методов IContext, то есть, вводя понятие версии IContext (но не версии Command). Это вполне рабочее решение, хотя и не слишком красивое. Если же отказаться от декларация классов команд в одном месте, то придется делать декларацию одной и той же команды в каждом получателе (и вводить различные IContext), что мне представляется гораздо большим злом, чем некоторая избыточность предложенного в статье решения.
Далее, Вы пишете — "Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы написать какого то конкретного получателя под конкрентную задачу".
Это одна из проблем — как указать получателя, если отправитель и получатель находятся в различных адресных пространствах? Поиск решения и привел к технике, описанной в статье, ведь при реализации команд в рамках одного адресного пространства оригинальный паттерн Command и так достаточно хорош.