Глянь мій новий курс по Git! Привіт! Глянь мій новий курс по Git! Привіт! Глянь мій новий курс по Git на GitByBit.com! Привіт! Хочеш класно освіжити Git? Глянь мій новий курс на GitByBit.com!
Стан

Стан на Ruby

Стан — це поведінковий патерн, що дозволяє динамічно змінювати поведінку об’єкта при зміні його стану.

Поведінки, які залежать від стану, переїзджають в окремі класи. Початковий клас зберігає посилання на один з таких об’єктів-станів та делегує йому роботу.

Складність:

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

Застосування: Патерн Стан часто використовують в Ruby для перетворення в об’єкти величезних стейт-машин, побудованих на операторах switch.

Ознаки застосування патерна: Методи класу делегують роботу одному вкладеному об’єктові.

Концептуальний приклад

Цей приклад показує структуру патерна Стан, а саме — з яких класів він складається, які ролі ці класи виконують і як вони взаємодіють один з одним.

main.rb: Приклад структури патерна

# The Context defines the interface of interest to clients. It also maintains a
# reference to an instance of a State subclass, which represents the current
# state of the Context.
class Context
  # A reference to the current state of the Context.
  attr_accessor :state
  private :state

  # @param [State] state
  def initialize(state)
    transition_to(state)
  end

  # The Context allows changing the State object at runtime.
  def transition_to(state)
    puts "Context: Transition to #{state.class}"
    @state = state
    @state.context = self
  end

  # The Context delegates part of its behavior to the current State object.

  def request1
    @state.handle1
  end

  def request2
    @state.handle2
  end
end

# The base State class declares methods that all Concrete State should implement
# and also provides a backreference to the Context object, associated with the
# State. This backreference can be used by States to transition the Context to
# another State.
class State
  attr_accessor :context

  # @abstract
  def handle1
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end

  # @abstract
  def handle2
    raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}'"
  end
end

# Concrete States implement various behaviors, associated with a state of the
# Context.

class ConcreteStateA < State
  def handle1
    puts 'ConcreteStateA handles request1.'
    puts 'ConcreteStateA wants to change the state of the context.'
    @context.transition_to(ConcreteStateB.new)
  end

  def handle2
    puts 'ConcreteStateA handles request2.'
  end
end

class ConcreteStateB < State
  def handle1
    puts 'ConcreteStateB handles request1.'
  end

  def handle2
    puts 'ConcreteStateB handles request2.'
    puts 'ConcreteStateB wants to change the state of the context.'
    @context.transition_to(ConcreteStateA.new)
  end
end

# The client code.

context = Context.new(ConcreteStateA.new)
context.request1
context.request2

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

Context: Transition to ConcreteStateA
ConcreteStateA handles request1.
ConcreteStateA wants to change the state of the context.
Context: Transition to ConcreteStateB
ConcreteStateB handles request2.
ConcreteStateB wants to change the state of the context.
Context: Transition to ConcreteStateA

Стан іншими мовами програмування

Стан на C# Стан на C++ Стан на Go Стан на Java Стан на PHP Стан на Python Стан на Rust Стан на Swift Стан на TypeScript