#c# #design-patterns
#c# #шаблоны проектирования
Вопрос:
Я, неосознанно, использовал шаблон команд, в котором клиент и вызывающий являются одинаковыми, и они вызывают команды напрямую. Посмотрев определение на DoFactory, я немного смущен.
Существуют отдельные команды. Это не изменилось с моего наивного понимания. Я предполагаю, что вызывающий просто вызывает все команды. Но какова цель получателя? Этого я не понимаю.
Если возможно, может кто-нибудь привести мне пример с несколькими командами и как приступить к реализации?
Комментарии:
1. Что именно вам непонятно? Отдельные обработчики команд или … ?
2. Я получаю отдельные команды. Это отдельная задача. Я не уверен, как «Приемник» вписывается в картину.
3. В моем предыдущем комментарии я имел в виду, что вы не можете понять, как работают обработчики команд (получатели в вашей формулировке)? Или вы имеете в виду события, вызванные обработчиками команд??
4. да, это именно то, в чем заключается мое замешательство.
Ответ №1:
Основная цель шаблона команд — отделить базовую (наиболее важную) операцию некоторых классов (конкретных классов команд) от их реального потребителя (CommandHandler ).
Итак, мы используем обходной путь, основанный на полиморфизме. Мы определяем абстрактный класс Command, у которого есть вызываемый метод void excecute(){}
, поэтому он не становится жестким с каким-либо параметром метода или типом возвращаемого значения. Таким образом, конкретные классы команд могут реализовывать свою специфичную для класса реализацию внутри этого метода, и обработчик команд может свободно вызывать someCommandObject.execute();
без необходимости знать, что именно этот конкретный класс (достаточно быть экземпляром Command class ). Таким образом, вызовы и реализации в значительной степени разделены. В будущем вы можете легко ввести другой конкретный командный класс, который реализует void execute(){}
, но обработчик команд может управлять этим вызовом someCommandObject.execute();
. В этом прелесть шаблона команд.
Это то же самое, что мы имеем Thread.run()
в потоках Java и Task.Run()
в потоках C #.
Хотя вы можете использовать приемник в соответствии с вашим удобством, он немного выбивается из общей картины командного шаблона. В вашем примере калькулятора имеет смысл иметь приемник, поскольку все конкретные классы команд могут ссылаться на него для выполнения своей основной операции( execute()
).
Вы можете увидеть несколько примеров здесь и там, где Приемник не использовался. Более чем идеально использовать приемник там, где это имеет смысл. Но не путайте это с реальным шаблоном команд. :))
Комментарии:
1. Хорошая работа 1! Сначала я подумал о CQS … 🙂
Ответ №2:
Участие Receiver
в этом шаблоне на самом деле не важно, это просто для того, чтобы подчеркнуть тот факт, что конкретный объект command, замаскированный за очень простым Command
интерфейсом, может сделать важную вещь, и даже эта вещь фактически обрабатывается другим object ( Receiver
), а не самим объектом command .
Действительно, суть шаблона команд заключается в том, чтобы инкапсулировать сложную задачу в минимальный интерфейс (просто метод void — void execute()
— который не требует никаких параметров), чтобы одна или несколько задач могли быть легко сохранены и переданы куда угодно для последующего вызова an Invoker
. Это очень удобно для Invoker
, поскольку Command
интерфейс минимален.
Наглядным примером Command
является хорошо известный Runnable
интерфейс на Java.
Комментарии:
1. Я подумал, что приемник можно было бы настроить для связи с различными системами. Например, нам нужно создать новую учетную запись пользователя, но создание нового пользователя предполагает взаимодействие с двумя системами. В этом случае будут созданы две команды… один для связи с system1, а второй для system2. Также будут созданы два приемника, один для command1, а другой для command2. Теперь, от имени клиента, вы вызываете две команды, и они будут знать, как связаться с соответствующей системой и выполнить задание. Правильно ли я думаю об этом?
2. Да, правильно. Таким образом, если вы хотите, после создания двух команд вы можете отложить выполнение, просто сохранить или передать их куда-нибудь, чтобы где-нибудь в подходящее время были выполнены команды и создан новый пользователь.
Ответ №3:
Простой пример шаблона проектирования команд в C#:
using System;
interface ICommand {
void Execute();
}
class Rifle : ICommand
{
public void Execute()
{
Console.WriteLine("Rifle is in action : Pif! Paf!");
}
}
class Cannon : ICommand
{
public void Execute()
{
Console.WriteLine("Cannon is in action : Bum! Bam!");
}
}
class Invoker
{
private ICommand _command;
public void SetCommand(ICommand command)
{
this._command = command;
}
public void Action()
{
_command.Execute();
}
}
class Client
{
static void Main()
{
ICommand command0 = new Rifle();
ICommand command1 = new Cannon();
///////////////////////////////
Invoker invoker = new Invoker();
invoker.SetCommand(command0);
invoker.Action();
invoker.SetCommand(command1);
invoker.Action();
Console.ReadKey();
}
}
/*output :
Rifle is in action : Pif! Paf!
Cannon is in action : Bum! Bam!
*/
Комментарии:
1. Вы что-то упускаете
Receiver
. Шаблон команд