Patrón State
Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 49 de 57.
El patrón de estado traslada el comportamiento que depende del estado actual de un objeto a objetos de estado independientes. El objeto principal, el contexto, contiene un estado y reenvía las llamadas a este; un estado responde y decide cuál será el siguiente estado:
class Red
def next_state
Green.new
end
def to_s
"red"
end
end
class Green
def next_state
Yellow.new
end
def to_s
"green"
end
end
class Yellow
def next_state
Red.new
end
def to_s
"yellow"
end
end
class TrafficLight
def initialize
@state = Red.new
end
def change
@state = @state.next_state
self
end
def to_s
"light is #{@state}"
end
end
light = TrafficLight.new
puts light
puts light.change
puts light.change.changeSalida:
light is red
light is green
light is redSin el patrón, cada método del contexto necesita un case sobre un valor de estado, y un estado nuevo implica editar todos ellos. Con objetos de estado, cada estado es una clase que contiene sus propias reglas:
# sin el patrón
def can_go?
case @status
when :red then false
when :green then true
when :yellow then false
end
end
# con el patrón
def can_go?
@state.can_go?
endLos estados pueden rechazar un evento que no corresponda. Aquí, un borrador no se puede publicar directamente; primero tiene que pasar por revisión:
class Draft
def submit
Review.new
end
def publish
raise ArgumentError, "cannot publish a draft"
end
def to_s
"draft"
end
end
class Review
def publish
Published.new
end
def to_s
"in review"
end
end
class Published
def to_s
"published"
end
end
state = Draft.new
begin
state.publish
rescue ArgumentError => e
puts e.message
end
state = state.submit
state = state.publish
puts stateSalida:
cannot publish a draft
publishedUna clase base compartida puede proporcionar la respuesta predeterminada a cada estado, como rechazar todos los eventos, de modo que cada estado solo defina los eventos que acepta:
class State
def submit
raise ArgumentError, "cannot submit #{self}"
end
def approve
raise ArgumentError, "cannot approve #{self}"
end
end
class Review < State
def approve
Published.new
end
endDesafío
FácilCompleta el semáforo. Los estados Red, Green y Yellow tienen cada uno next_state (red pasa a green, green a yellow, yellow a red), can_go? (solo green) y to_s (el color). TrafficLight comienza en red, change pasa al siguiente estado y status devuelve red: stop o green: go, preguntándole al estado.
El código proporcionado lee los comandos change o status e imprime el estado después de cada comando.
Tu código debe ir en red.rb, green.rb, yellow.rb y traffic_light.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.
Pruébalo tú mismo
require_relative 'red'
require_relative 'green'
require_relative 'yellow'
require_relative 'traffic_light'
# Código de entrada/salida suministrado: déjalo tal como está
input = []
while (line = gets)
input << line.chomp
end
light = TrafficLight.new
input.each do |cmd|
light.change if cmd == "change"
puts light.status
end
Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.
Todas las lecciones de Programación orientada a objetos
1Clases y objetos
Trabajar con archivosDefinir clasesVariables de instanciaMétodos y selfto_s e inspectRepaso: tarjeta de biblioteca4Encapsulación
Métodos privadosMétodos protegidosAsignadores privadosProtección del estadoRepaso: máquina expendedora7Polimorfismo y tipado pato
PolimorfismoTipado patoMétodos abstractoscase y clasesRepaso: métodos de pago2Accesores y self
Lectores y escritoresSetters personalizadosself en los métodosIdentidad e igualdadRepaso: lista de contactos5Herencia
SubclasesSobrescritura de métodosLlamar a superis_a? y ancestrosRepaso - Nómina del personal8Métodos especiales
Igualdad y hashMétodos de operadoresIndexación y adiciónColecciones personalizadasRepaso: fracciones11Proyecto: Gestión de biblioteca
Libros y miembrosPréstamo de librosPractica por tu cuenta: Compilador de Ruby online