Шаблон объекта команды подражатель или реальная вещь? - PullRequest
6 голосов
/ 09 сентября 2011

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

Позвольте мне показать это вам (по соображениям конфиденциальности этобудет очень упрощен, но я приложу все усилия, чтобы показать основные понятия):

public class CommandOne
{
   public CommandOne(Manager manager, MyForm form)
   {
      m_manager = manager;
      m_form = form;
   }

   public void Execute()
   {
       m_manager.CommandOne(m_form);
   }
}

public class CommandTwo
{
   public CommandTwo(Manager manager, MyForm form)
   {
      m_manager = manager;
      m_form = form;
   }

   public void Execute()
   {
       m_manager.CommandTwo(m_form);
   }
}

Первое, что кажется мне странным, это то, что эти два класса не наследуются ни от какого абстрактного класса, ни реализуютобщий интерфейс.

Код, который использует эти команды, выглядит следующим образом:

public class MyForm : System.Windows.Forms.Form
{
   public MyForm(Manager manager)
   {
      m_manager = manager;
   }

   private void SomeMethod()
   {
      ....
      var cmd = new CommandOne(manager, this);
      cmd.Execute();
      ...
   }

   private void OtherMethod()
   {
      ....
      var cmd = new CommandTwo(manager, this);
      cmd.Execute();
      ...
   }
}

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

Так может кто-нибудь объяснить, какие части, если таковые имеются, отсутствует в этой реализации, чтобы действительно быть шаблоном командного объекта, и, хотя это может быть слишком субъективно, какая польза от его реализации в этом случае?

Спасибо.

1 Ответ

11 голосов
/ 09 сентября 2011

Исходя из того, что вы показываете здесь, похоже, что преимущество шаблона команды потеряно.Есть несколько причин, по которым вы можете захотеть использовать шаблон команды в контексте приложения WinForms.

Вы хотите выполнить команду позже

public interface ICommand
{
    void Execute();
}

Сохраните историю выполненных команд, чтобыони могут быть отменены пользователем

public interface ICommand
{
    void Execute();

    void Undo();
}

Проверьте разрешения, чтобы увидеть, есть ли у текущего пользователя права на выполнение команды.Например, возможно, у вас есть RefundCustomerCommand, и не все агенты по обслуживанию клиентов имеют право выдать возмещение, поэтому вы хотите отключить кнопку в форме.

public interface ICommand
{
    void Execute();

    bool CanExecute { get; }
}

Вы также можете объединить несколько командв композите, подобном этому:

public class CompositeCommand : ICommand
{
    private readonly List<ICommand> commands;

    public CompositeCommand()
    {
        commands = new List<ICommand>();
    }

    public void Add(ICommand command)
    {
        commands.Add(command);
    }

    public void Execute()
    {
        foreach (var command in commands) command.Execute();
    }
}

Шаблон команды также прекрасно работает с декоратором.Вы можете легко добавить в свои команды дополнительное сквозное поведение, например, логику повтора:

public class RetryOnTimeout : ICommand
{
    private readonly ICommand command;
    private int numberOfRetries;

    public RetryOnTimeout(ICommand command, int numberOfRetries)
    {
        this.command = command;
        this.numberOfRetries = numberOfRetries;
    }

    public void Execute()
    {
        try
        {
            command.Execute();
        }
        catch (TimeoutException)
        {
            if (++numberOfRetries > 3)
                throw;

            Execute();
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...