⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sect05.htm

📁 Pythn design pattern
💻 HTM
📖 第 1 页 / 共 4 页
字号:
    <font color=#0000ff>return</font> StateT.next(self, input)

<font color=#0000ff>class</font> Trapping(StateT):
  <font color=#0000ff>def</font> run(self):
    <font color=#0000ff>print</font> <font color=#004488>"Trapping: Closing door"</font>
  <font color=#0000ff>def</font> next(self, input):
    # Lazy initialization:
    <font color=#0000ff>if</font> <font color=#0000ff>not</font> self.transitions:
      self.transitions = {
        MouseAction.escapes : MouseTrap.waiting,
        MouseAction.trapped : MouseTrap.holding
      }
    <font color=#0000ff>return</font> StateT.next(self, input)

<font color=#0000ff>class</font> Holding(StateT):
  <font color=#0000ff>def</font> run(self):
    <font color=#0000ff>print</font> <font color=#004488>"Holding: Mouse caught"</font>
  <font color=#0000ff>def</font> next(self, input):
    # Lazy initialization:
    <font color=#0000ff>if</font> <font color=#0000ff>not</font> self.transitions:
      self.transitions = {
        MouseAction.removed : MouseTrap.waiting
      }
    <font color=#0000ff>return</font> StateT.next(self, input)

<font color=#0000ff>class</font> MouseTrap(StateMachine):
  <font color=#0000ff>def</font> __init__(self): 
    # Initial state
    StateMachine.__init__(self, MouseTrap.waiting)

# Static variable initialization:
MouseTrap.waiting = Waiting()
MouseTrap.luring = Luring()
MouseTrap.trapping = Trapping()
MouseTrap.holding = Holding()

moves = map(string.strip, 
  open(<font color=#004488>"..</font><font color=#004488>/mouse</font><font color=#004488>/MouseMoves.txt"</font>).readlines())
mouseMoves = map(MouseAction, moves)
MouseTrap().runAll(mouseMoves)
#:~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The rest of the code is
identical &#150; the difference is in the <B>next(&#160;)</B> methods and the
<B>StateT</B> class.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_158">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If you have to create and maintain a lot
of <B>State</B> classes, this approach is an improvement, since it&#146;s
easier to quickly read and understand the state transitions from looking at the
table.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_159">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><A NAME="_Toc534420087"></A><BR></P></DIV>
<A NAME="Heading38"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H2 ALIGN="LEFT">
Table-Driven State Machine</H2></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The advantage of the previous design is
that all the information about a state, including the state transition
information, is located within the state class itself. This is generally a good
design principle.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_160">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">However, in a pure state machine, the
machine can be completely represented by a single state-transition table. This
has the advantage of locating all the information about the state machine in a
single place, which means that you can more easily create and maintain the table
based on a classic state-transition diagram.
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_161">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The classic state-transition diagram uses
a circle to represent each state, and lines from the state pointing to all
states that state can transition into. Each transition line is annotated with
conditions for transition and an action during transition. Here&#146;s what it
looks like:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_162">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">(Simple State Machine Diagram)
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_163">Add Comment</A></FONT><BR></P></DIV>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Goals:</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Georgia">translation of state diagram
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_164">Add Comment</A></FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Vector
of change: the state diagram representation
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_165">Add Comment</A></FONT><LI><FONT FACE="Georgia">implementation
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_166">Add Comment</A></FONT><LI><FONT FACE="Georgia">excess
of states (you could represent every single change with a new state)
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_167">Add Comment</A></FONT><LI><FONT FACE="Georgia">and
flexibility
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_168">Add Comment</A></FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Observations:</FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">States are trivial &#150;
no information or functions/data, just an identity
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_169">Add Comment</A></FONT><LI><FONT FACE="Georgia">like
the State pattern!
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_170">Add Comment</A></FONT><LI><FONT FACE="Georgia">machine
governs the move from state to state
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_171">Add Comment</A></FONT><LI><FONT FACE="Georgia">to
flyweight
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_172">Add Comment</A></FONT><LI><FONT FACE="Georgia">state
may move to many others
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_173">Add Comment</A></FONT><LI><FONT FACE="Georgia">&amp;
action functions must also be external to states
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_174">Add Comment</A></FONT><LI><FONT FACE="Georgia">description
in a single table containing all variations, for ease of configuration
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_175">Add Comment</A></FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">Example:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_176">Add Comment</A></FONT><BR></P></DIV>
<UL>
<LI><FONT FACE="Georgia">Machine &amp; Table-Driven Code
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_177">Add Comment</A></FONT><LI><FONT FACE="Georgia">a
vending machine
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_178">Add Comment</A></FONT><LI><FONT FACE="Georgia">several
other patterns
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_179">Add Comment</A></FONT><LI><FONT FACE="Georgia">common
state-machine code from specific application (like template method)
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_180">Add Comment</A></FONT><LI><FONT FACE="Georgia">input
causes a seek for appropriate solution (like chain of responsibility)
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_181">Add Comment</A></FONT><LI><FONT FACE="Georgia">and
transitions are encapsulated in function objects (objects that hold functions)
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_182">Add Comment</A></FONT><LI><FONT FACE="Symbol">	</FONT><FONT FACE="Georgia">Java
constraint: methods are not first-class objects
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_183">Add Comment</A></FONT></UL><DIV ALIGN="LEFT"><P><FONT FACE="Georgia"><IMG SRC="TIPyth01.gif"></FONT><A NAME="_Toc534420088"></A><BR></P></DIV>
<A NAME="Heading39"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
The State class</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>State</B> class is distinctly
different from before, since it is really just a placeholder with a name. Thus
it is not inherited from previous <B>State</B> classes:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_184">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:statemachine2:State.py

<font color=#0000ff>class</font> State:
  <font color=#0000ff>def</font> __init__(self, name): self.name = name
  <font color=#0000ff>def</font> __str__(self): <font color=#0000ff>return</font> self.name 
# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc534420089"></A><BR></P></DIV>
<A NAME="Heading40"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Conditions for transition</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">In the state transition diagram, an input
is tested to see if it meets the condition necessary to transfer to the state
under question. As before, the <B>Input</B> is just a tagging interface:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_185">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:statemachine2:Input.py
# Inputs to a state machine

<font color=#0000ff>class</font> Input: <font color=#0000ff>pass</font>
# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><FONT FACE="Georgia">The <B>Condition</B> evaluates
the <B>Input</B> to decide whether this row in the table is the correct
transition:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_186">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:statemachine2:Condition.py
# Condition function object <font color=#0000ff>for</font> state machine

<font color=#0000ff>class</font> Condition:
  boolean condition(input) : 
    <font color=#0000ff>assert</font> 1, <font color=#004488>"condition() not implemented"</font>
# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc534420090"></A><BR></P></DIV>
<A NAME="Heading41"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Transition actions</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">If the <B>Condition</B> returns
<B>true</B>, then the transition to a new state is made, and as that transition
is made some kind of action occurs (in the previous state machine design, this
was the <B>run(&#160;)</B> method):
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_187">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:statemachine2:Transition.py
# Transition function object <font color=#0000ff>for</font> state machine

<font color=#0000ff>class</font> Transition:
  <font color=#0000ff>def</font> transition(self, input):
    <font color=#0000ff>assert</font> 1, <font color=#004488>"transition() not implemented"</font>
# :~<A NAME=<font color=#004488>"_Toc534420091"</font>></A></PRE></FONT></BLOCKQUOTE><A NAME="Heading42"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
The table</H3></FONT>
<DIV ALIGN="LEFT"><P><FONT FACE="Georgia">With these classes in place, we can set
up a 3-dimensional table where </FONT><FONT FACE="Georgia">each row completely
describes a state. The first element in the row is the current state, and the
rest of the elements are each a row indicating what the <I>type </I>of the input
can be, the condition that must be satisfied in order for this state change to
be the correct one, the action that happens during transition, and the new state
to move into. Note that the <B>Input</B> object is not just used for its type,
it is also a <I>Messenger</I> object that carries information to the
<B>Condition</B> and <B>Transition</B> objects:
<A HREF="http://www.mindview.net/Books/TIPython/BackTalk/FindPage/A_188">Add Comment</A></FONT><BR></P></DIV>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE>{(CurrentState, InputA) : (ConditionA, TransitionA, NextA),
 (CurrentState, InputB) : (ConditionB, TransitionB, NextB),
 (CurrentState, InputC) : (ConditionC, TransitionC, NextC),
 ...
}
</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc534420092"></A><BR></P></DIV>
<A NAME="Heading43"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
The basic machine</H3></FONT>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:statemachine2:StateMachine.py
# A table-driven state machine

<font color=#0000ff>class</font> StateMachine:
  <font color=#0000ff>def</font> __init__(self, initialState, tranTable):
    self.state = initialState
    self.transitionTable = tranTable

  <font color=#0000ff>def</font> nextState(self, input):
    
    Iterator it=((List)map.get(state)).iterator()
    <font color=#0000ff>while</font>(it.hasNext()):
      Object[] tran = (Object[])it.next()
      <font color=#0000ff>if</font>(input == tran[0] || 
         input.getClass() == tran[0]):
        <font color=#0000ff>if</font>(tran[1] != null):
          Condition c = (Condition)tran[1]
          <font color=#0000ff>if</font>(!c.condition(input))
            <font color=#0000ff>continue</font> # Failed test
        
        <font color=#0000ff>if</font>(tran[2] != null)
          ((Transition)tran[2]).transition(input)
        state = (State)tran[3]
        <font color=#0000ff>return</font>
      

    throw RuntimeException(
      <font color=#004488>"Input not supported for current state"</font>)

# :~</PRE></FONT></BLOCKQUOTE><DIV ALIGN="LEFT"><P><A NAME="_Toc534420093"></A><BR></P></DIV>
<A NAME="Heading44"></A><FONT FACE = "Verdana, Tahoma, Arial, Helvetica, Sans"><H3 ALIGN="LEFT">
Simple vending machine</H3></FONT>

<BLOCKQUOTE><FONT SIZE = "+1"><PRE># c04:vendingmachine:VendingMachine.py
# Demonstrates use of StateMachine.py
<font color=#0000ff>import</font> sys
sys.path += ['../statemachine2']
<font color=#0000ff>import</font> StateMachine

<font color=#0000ff>class</font> State:
  <font color=#0000ff>def</font> __init__(self, name): self.name = name
  <font color=#0000ff>def</font> __str__(self): <font color=#0000ff>return</font> self.name 

State.quiescent = State(<font color=#004488>"Quiesecent"</font>)
State.collecting = State(<font color=#004488>"Collecting"</font>)
State.selecting = State(<font color=#004488>"Selecting"</font>)
State.unavailable = State(<font color=#004488>"Unavailable"</font>)
State.wantMore = State(<font color=#004488>"Want More?"</font>)
State.noChange = State(<font color=#004488>"Use Exact Change Only"</font>)
State.makesChange = State(<font color=#004488>"Machine makes change"</font>)

<font color=#0000ff>class</font> HasChange:
  <font color=#0000ff>def</font> __init__(self, name): self.name = name
  <font color=#0000ff>def</font> __str__(self): <font color=#0000ff>return</font> self.name 

HasChange.yes = HasChange(<font color=#004488>"Has change"</font>)
HasChange.no = HasChange(<font color=#004488>"Cannot make change"</font>)

<font color=#0000ff>class</font> ChangeAvailable(StateMachine):
  <font color=#0000ff>def</font> __init__(self):
    StateMachine.__init__(State.makesChange, {
      # Current state, input
      (State.makesChange, HasChange.no) :
        # test, transition, next state:
        (null, null, State.noChange),
      (State.noChange, HasChange.yes) :
        (null, null, State.noChange)
    })

<font color=#0000ff>class</font> Money:

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -