Padrão State
Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 49 de 57.
O padrão de estado move o comportamento que depende do estado atual de um objeto para objetos de estado separados. O objeto principal, o contexto, mantém um estado e encaminha as chamadas para ele; um estado responde e decide qual estado vem a seguir:
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.changeSaída:
light is red
light is green
light is redSem o padrão, cada método do contexto precisa de um case sobre um valor de status, e um novo estado significa editar todos eles. Com objetos de estado, cada estado é uma classe que contém suas próprias regras:
# sem o padrão
def can_go?
case @status
when :red then false
when :green then true
when :yellow then false
end
end
# com o padrão
def can_go?
@state.can_go?
endOs estados podem recusar um evento que não seja adequado. Aqui, um rascunho não pode ser publicado diretamente; primeiro, ele precisa passar por revisão:
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 stateSaída:
cannot publish a draft
publishedUma classe base compartilhada pode fornecer a resposta padrão para cada estado, como recusar todos os eventos, para que cada estado defina apenas os eventos que aceita:
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
endDesafio
FácilComplete o semáforo. Os estados Red, Green e Yellow têm, cada um, next_state (red vai para green, green para yellow, yellow para red), can_go? (apenas green) e to_s (a cor). TrafficLight começa em red, change move para o próximo estado, e status retorna red: stop ou green: go, consultando o estado.
O código fornecido lê os comandos change ou status e imprime o status após cada comando.
Seu código deve estar em red.rb, green.rb, yellow.rb e traffic_light.rb. main.rb contém o código fornecido de entrada/saída e não pode ser editado.
Experimente você mesmo
require_relative 'red'
require_relative 'green'
require_relative 'yellow'
require_relative 'traffic_light'
# Código de entrada/saída fornecido: mantenha-o 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 lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Programação orientada a objetos
1Classes e Objetos
Trabalhando com ArquivosDefinindo ClassesVariáveis de InstânciaMétodos e selfto_s e inspectRevisão - Cartão da Biblioteca4Encapsulamento
Métodos privadosMétodos protegidosSetters privadosProtegendo o estadoRevisão - Máquina de venda automática7Polimorfismo e Duck Typing
PolimorfismoDuck TypingMétodos Abstratoscase e ClassesRevisão - Métodos de Pagamento2Acessores e self
Leitores e GravadoresSetters Personalizadosself nos MétodosIdentidade e IgualdadeRecapitulação - Lista de Contatos5Herança
SubclassesSobrescrita de métodosChamando superis_a? e ancestraisRevisão - Folha de pagamento da equipe8Métodos Especiais
Igualdade e hashMétodos de OperadoresIndexação e AdiçãoColeções PersonalizadasRevisão - Frações11Projeto: Gerenciamento de Biblioteca
Livros e MembrosEmpréstimo de LivrosPratique por conta própria: Compilador de Ruby online