我正在python中实现状态设计模式的可靠实现。在这样做的过程中,我发现了两种做事方式。
方式1
class State(object):
transitions = [(None, None, None)]
def __init__(self, state_context):
self._context = state_context
self.set_transitions()
def set_transitions(self):
"""subclass may override this if access to self is
needed in transitions"""
pass
def __call__(self, inp):
new_state = self
state_action_list = [(state, action) for cls, state,
action in self.transitions if
isinstance(inp, cls)]
if 1 == len(state_action_list):
state, action = state_action_list[0]
if action is not None:
action(inp)
new_state = globals()[state](self._context)
elif 1 < len(state_action_list):
raise AmbiguousTransitionError(inp, self)
return new_state
允许这种用法:
class StateA(State):
transitions = [(MsgA, "StateB", None)]
class StateB(State):
def set_transitions(self):
self.transitions = [(MsgB, "StateC", self._print_msg)]
@staticmethod
def _print_msg(inp):
print "Inp: ", inp
class StateC(State):
def set_transitions(self):
self.transitions = [(MsgB, "StateB", None),
(MsgC, "StateA", self._print_context)]
def _print_context(self, unused_inp):
"""example"""
print "Context: ", self._context
这里是Way 2的改变
def __call__(self, inp):
[...]
if action is not None:
try:
action(inp)
except TypeError:
action(self, inp)
new_state = state(self._context)
[...]
用法:
class StateA(State): pass
class StateB(State):
@staticmethod
def _print_msg(inp):
print "Inp: ", inp
class StateC(State):
def _print_context(self, unused_inp):
"""example"""
print "Context: ", self._context
StateA.transitions = [(MsgA, StateB, None)]
StateB.transitions = [(MsgB, StateC, StateB._print_msg)]
StateC.transitions = [(MsgB, StateB, None),
(MsgC, StateA, StateC._print_context)]
我遇到的问题是:
globals()
来上课,这本身会带来各种麻烦set_transitions
解决方法将方法用作操作然而我对选项号的关注。 2是:
except TypeError:
块来允许将静态方法用作操作现在的问题是,哪种方式更可取? No1可读性可能更好吗?
也许我还没有看到另一个第三种选择?
提前感谢您的任何反馈!
/马丁
BTW这里是一个独立于两个选项的示例用法:
class Context(object):
def __init__(self):
self._state = StateA(self)
def handle(self, msg):
self._state = self._state(msg)
if __name__ == "__main__":
CONTEXT = Context()
CONTEXT.handle(MsgA())
CONTEXT.handle(MsgB())
CONTEXT.handle(MsgC())
CONTEXT.handle(MsgB())