![State](/images/patterns/cards/state-mini.png?id=f4018837e0641d1dade756b6678fd4ee)
State en Ruby
State es un patrón de diseño de comportamiento que permite a un objeto cambiar de comportamiento cuando cambia su estado interno.
El patrón extrae comportamientos relacionados con el estado, los coloca dentro de clases de estado separadas y fuerza al objeto original a delegar el trabajo de una instancia de esas clases, en lugar de actuar por su cuenta.
Complejidad:
Popularidad:
Ejemplos de uso: El patrón State se utiliza habitualmente en Ruby para convertir las enormes máquinas de estados basadas en switch
, en objetos.
Identificación: El patrón State se puede reconocer por métodos que cambian su comportamiento dependiendo del estado del objeto, controlado externamente.
Ejemplo conceptual
Este ejemplo ilustra la estructura del patrón de diseño State. Se centra en responder las siguientes preguntas:
- ¿De qué clases se compone?
- ¿Qué papeles juegan esas clases?
- ¿De qué forma se relacionan los elementos del patrón?
main.rb: Ejemplo conceptual
# 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: Resultado de la ejecución
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