Autumn SALE
Команда

Команда на Ruby

Команда — это поведенческий паттерн, позволяющий заворачивать запросы или простые операции в отдельные объекты.

Это позволяет откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.

Сложность:

Популярность:

Применимость: Паттерн можно часто встретить в Ruby-коде, особенно когда нужно откладывать выполнение команд, выстраивать их в очереди, а также хранить историю и делать отмену.

Признаки применения паттерна: Классы команд построены вокруг одного действия и имеют очень узкий контекст. Объекты команд часто подаются в обработчики событий элементов GUI. Практически любая реализация отмены использует принципа команд.

Концептуальный пример

Этот пример показывает структуру паттерна Команда, а именно — из каких классов он состоит, какие роли эти классы выполняют и как они взаимодействуют друг с другом.

main.rb: Пример структуры паттерна

# Интерфейс Команды объявляет метод для выполнения команд.
#
# @abstract
class Command
  # @abstract
  def execute
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# Некоторые команды способны выполнять простые операции самостоятельно.
class SimpleCommand < Command
  # @param [String] payload
  def initialize(payload)
    @payload = payload
  end

  def execute
    puts "SimpleCommand: See, I can do simple things like printing (#{@payload})"
  end
end

# Но есть и команды, которые делегируют более сложные операции другим объектам,
# называемым «получателями».
class ComplexCommand < Command
  # Сложные команды могут принимать один или несколько объектов-получателей
  # вместе с любыми данными о контексте через конструктор.
  #
  # @param [Receiver] receiver
  # @param [String] a
  # @param [String] b
  def initialize(receiver, a, b)
    @receiver = receiver
    @a = a
    @b = b
  end

  # Команды могут делегировать выполнение любым методам получателя.
  def execute
    print 'ComplexCommand: Complex stuff should be done by a receiver object'
    @receiver.do_something(@a)
    @receiver.do_something_else(@b)
  end
end

# Классы Получателей содержат некую важную бизнес-логику. Они умеют выполнять
# все виды операций, связанных с выполнением запроса. Фактически, любой класс
# может выступать Получателем.
class Receiver
  # @param [String] a
  def do_something(a)
    print "\nReceiver: Working on (#{a}.)"
  end

  # @param [String] b
  def do_something_else(b)
    print "\nReceiver: Also working on (#{b}.)"
  end
end

# Отправитель связан с одной или несколькими командами. Он отправляет запрос
# команде.
class Invoker
  # Инициализация команд.

  # @param [Command] command
  def on_start=(command)
    @on_start = command
  end

  # @param [Command] command
  def on_finish=(command)
    @on_finish = command
  end

  # Отправитель не зависит от классов конкретных команд и получателей.
  # Отправитель передаёт запрос получателю косвенно, выполняя команду.
  def do_something_important
    puts 'Invoker: Does anybody want something done before I begin?'
    @on_start.execute if @on_start.is_a? Command

    puts 'Invoker: ...doing something really important...'

    puts 'Invoker: Does anybody want something done after I finish?'
    @on_finish.execute if @on_finish.is_a? Command
  end
end

# Клиентский код может параметризовать отправителя любыми командами.
invoker = Invoker.new
invoker.on_start = SimpleCommand.new('Say Hi!')
receiver = Receiver.new
invoker.on_finish = ComplexCommand.new(receiver, 'Send email', 'Save report')

invoker.do_something_important

output.txt: Результат выполнения

Invoker: Does anybody want something done before I begin?
SimpleCommand: See, I can do simple things like printing (Say Hi!)
Invoker: ...doing something really important...
Invoker: Does anybody want something done after I finish?
ComplexCommand: Complex stuff should be done by a receiver object
Receiver: Working on (Send email.)
Receiver: Also working on (Save report.)

Команда на других языках программирования

Команда на C# Команда на C++ Команда на Go Команда на Java Команда на PHP Команда на Python Команда на Rust Команда на Swift Команда на TypeScript