
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