Расширение возможностей паттерна Command
От: Сергей Гурин  
Дата: 28.12.04 08:15
Оценка: 120 (6)
Статья:
Расширение возможностей паттерна Command
Автор(ы): Сергей Гурин
Дата: 02.05.2005
В статье описывается расширение паттерна Command, которое позволяет командам выполняться в различных контекстах и пересекать границы приложения и компьютера.


Авторы:
Сергей Гурин

Аннотация:
В статье описывается расширение паттерна Command, которое позволяет командам выполняться в различных контекстах и пересекать границы приложения и компьютера.
Re: Расширение возможностей паттерна Command
От: LCR Россия lj://_lcr_
Дата: 04.05.05 15:31
Оценка:
Здравствуйте, Сергей Гурин, Вы писали:

Диаграмка красивая
quicksort =: (($:@(<#[),(=#[),$:@(>#[)) ({~ ?@#)) ^: (1<#)
Re: Расширение возможностей паттерна Command
От: Аноним  
Дата: 05.05.05 04:21
Оценка:
Здравствуйте, Сергей Гурин!

В общем мысль неплохая, но есть противоречия и неудобства:
Противоречие:
Вы писали что
"Для расширения или изменения функциональности создавайте новый класс команды, оставляя существующий класс без изменений. Старые программы (или фрагменты программ) смогут при этом работать без изменений, а новые программы будут использовать расширенные возможности."
Но при добавлении нового класса будет изменен интерфейс IContext, который также как и класс Command опубликован и соответсвенно изменение его не желательно, так как влечет изменение всех получателей.
Неудобства:
Все получатели должны знать все команды,
Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы и др. "Приемы объектно-ориентированного проектирования",написать какого то конкретного получателя под конкрентную задачу.
Re: Расширение возможностей паттерна Command
От: Аноним  
Дата: 05.05.05 08:01
Оценка:

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


Стоило из-за этого такой велосипедище строить.
Re[2]: Расширение возможностей паттерна Command
От: rsdn_gurin  
Дата: 05.05.05 14:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, Сергей Гурин!


А>В общем мысль неплохая, но есть противоречия и неудобства:

А>Противоречие:
А> Вы писали что
А>"Для расширения или изменения функциональности создавайте новый класс команды, оставляя существующий класс без изменений. Старые программы (или фрагменты программ) смогут при этом работать без изменений, а новые программы будут использовать расширенные возможности."
А> Но при добавлении нового класса будет изменен интерфейс IContext, который также как и класс Command опубликован и соответсвенно изменение его не желательно, так как влечет изменение всех получателей.
А> Неудобства:
А> Все получатели должны знать все команды,
А>Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы и др. "Приемы объектно-ориентированного проектирования",написать какого то конкретного получателя под конкрентную задачу.

Ответ от автора.

IContext в принципе не может оставаться стабильным при расширении набора команд. Но получатель будет распознавать (создавать с помощью фабрики классов) только те команды, которые были заложены при его разработке. То есть, совершенно не нужно переделывать старых получателей при появлении новых команд (конечно, если получатели реализованы в отдельных exe или dll-файлах). Но при эволюции старого получателя и его перекомпиляции, действительно приходится добавлять весь набор новых команд. Это естественная плата за контроль типов команд на этапе компиляции и за единственность декларации. Если получателю команда не нужна, то ее можно сделать в виде заглушки при реализации IReceiver и не регистрировать команду для фабрики классов (чтобы она вообще никогда не создавалась у данного получателя). Можно несколько сгладить обсуждаемый недостаток, если воспользоваться средствами макрообработки (директивами #ifdef в Си++ или {$IFDEF} в Delphi) разрешая включение в код групп команд и соответствующих методов IContext, то есть, вводя понятие версии IContext (но не версии Command). Это вполне рабочее решение, хотя и не слишком красивое. Если же отказаться от декларация классов команд в одном месте, то придется делать декларацию одной и той же команды в каждом получателе (и вводить различные IContext), что мне представляется гораздо большим злом, чем некоторая избыточность предложенного в статье решения.

Далее, Вы пишете — "Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы написать какого то конкретного получателя под конкрентную задачу".

Это одна из проблем — как указать получателя, если отправитель и получатель находятся в различных адресных пространствах? Поиск решения и привел к технике, описанной в статье, ведь при реализации команд в рамках одного адресного пространства оригинальный паттерн Command и так достаточно хорош.
Re[2]: Расширение возможностей паттерна Command
От: rsdn_gurin  
Дата: 05.05.05 14:51
Оценка:
Здравствуйте, Аноним, Вы писали:

А>

А>В данной статье мы не будем рассматривать общий случай, а ограничимся только достаточно важным частным случаем, когда отправители и получатели реализованы на одном и том же языке в рамках одной и той же платформы.


А>Стоило из-за этого такой велосипедище строить.


От автора: это может показаться неожиданным, но в конкретной реализации все получается довольно просто. Конечно, эту
задачу, как и любую другую, можно решить множеством способов. Я описал тот способ, который нашел и успешно
применил в одном из своих проектов.
Re[3]: Расширение возможностей паттерна Command
От: Аноним  
Дата: 06.05.05 07:02
Оценка: 2 (1)
Здравствуйте, rsdn_gurin!

Мне кажется есть более красивое решение
Надо изменить обявление получателя, в статье он был описан как:

SomeReceiver = class(BaseReceiver, IReceiver, )
public
...

изменить на

BaseReceiver = class(..., IContext)
...

SomeReceiver = class(BaseReceiver, IReceiver)
public
...

то есть вынести реализацию IContext в базовый класс, в котором они будут реализованы в виде
заглушек, то есть например

procedure BaseReceiver.ExecuteCommand1(cmd: Command1);
begin

end;

Тогда при изменении IContext меняется только базовый класс, не нужно менять
всех получателей, а конкретный получатель будет уже реализовывать(переопределяя пустую реализацию базового класса)
только те комманды которые его интересует.

А теперь по поводу того что я писал:
"Было бы удобно как в паттерне команда описанном в книге Эриха Гаммы написать
какого то конкретного получателя под конкрентную задачу".
Тут меня Вы маленько неправильно поняли, Вы написали в ответе:
Это одна из проблем — как указать получателя, если отправитель и
получатель находятся в различных адресных пространствах?
Эту проблему Вы прекрасно решили в статье, отправляя команду и задавая строкой получателя.

Объсню на примере что я хотел.
Допустим надо сделать получателя чтобы он обрабатывал только команду Command1, на остальные
не реагировал.
Тогда получатель будет выглядеть следующим образом:

SomeReceiver = class(BaseReceiver, IReceiver, IContext)
public
// интерфейс IContext
procedure ExecuteCommand1(cmd: Command1);
procedure ExecuteCommand2(cmd: Command2);
....
procedure ExecuteCommandN(cmd: CommandN);
end;

procedure SomeReceiver.ExecuteCommand1(cmd: Command1);
begin
// Что делаем ....
...
end;

procedure SomeReceiver.ExecuteCommand2(cmd: Command1);
begin

end;

...

procedure SomeReceiver.ExecuteCommandN(cmd: CommandN);
begin

end;

Получается что только один метод используется полноценно, остальные просто пустые, и при изменении IContext
он должен все время меняться, хотя функционал у него будет всегда один и тот же (ExecuteCommand1).
Когда я задавал Вам вопрос, я еще не додумался что достаточно реализацию IContext вынести в базовый класс (хотя решение типовое),чтобы получить то, что мне хочется.
если это сделать то получатель будет выглядеть следующим образом:

SomeReceiver = class(BaseReceiver, IReceiver)
public
procedure ExecuteCommand1(cmd: Command1); override;
end;

procedure SomeReceiver.ExecuteCommand1(cmd: Command1);
begin
// Что делаем ....
...
end;

Остальные команды его не интересуют он их не переопределяет. То есть получилось мы сделали
конкретного получателя под конкретную команду, не заграмождая его пустой реализацией других команд,
которые его не интересуют, и при добавлении новых команд он изменяться никак не будет. Вот это я и хотел.
Еще раз повторюсь идея интересная, самое главное что оформлено в виде четкой и понятной концепции.
Спасибо за внимание
Re[4]: Расширение возможностей паттерна Command
От: rsdn_gurin  
Дата: 06.05.05 12:40
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, rsdn_gurin!


А>Мне кажется есть более красивое решение

А>Надо изменить обявление получателя

От автора.

Большое спасибо, очень хорошее предложение. Полностью его принимаю.
Замечательно, когда в процессе обсуждения возникают такие предложения.
Еще раз спасибо.
Re[2]: Расширение возможностей паттерна Command
От: Аноним  
Дата: 01.06.06 13:47
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Стоило из-за этого такой велосипедище строить.


Стоило. . Да и велосипедиЩА не вышло, а так, маленький, трехколесный ... Но как раз на 100% подошел к моей задаче
Да и как я понял, идея неплохо переносится на другой язык.

Вобщем спасибо автору за статью...лучше поздно, чем никогда
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.