[PHP打野] 對pear-FSM的研究(一)基本瞭解

FSM(有限狀態機)是啥? php

有限狀態機英語finite-state machine縮寫FSM)又稱有限狀態自動機,簡稱狀態機,是表示有限個狀態以及在這些狀態之間的轉移和動做等行爲的數學模型git

詳細請看維基百科,FSM(http://zh.wikipedia.org/wiki/%E6%9C%89%E9%99%90%E7%8A%B6%E6%80%81%E6%9C%BA)。自動機編程(http://zh.wikipedia.org/wiki/%E8%87%AA%E5%8A%A8%E6%9C%BA%E7%BC%96%E7%A8%8B) 程序員

簡單來講,這玩意用於事物有多種狀態,主要在狀態之間變來變去的場景,你很想用個goto跳到上面的某個if的地方。 好比一個魔方,好比形式語言分析,好比魔獸世界戰士戰鬥姿態防護姿態狂暴姿態角鬥士姿態,好比模擬一堆電路元件…… 一般對於此類問題,若是輸入條件是能夠徹底預知的,那麼能夠經過寫while裏套一堆if then,或者switch case來處理,或者經過構造一個「圖」的數據結構更彈性些。(固然也有某些比較狂熱的方式好比弄無數層對象來折騰程序員本身和機器)可是這些方式不夠接近機器與數學的本質,也難以應對未知條件。 今天,爲尋求遠古強大的元素力量,我將帶你深刻不毛之地,研究研究php裏pear-FSM。 github

下載地址是 編程

http://pear.php.net/package/FSM vim

做者後來也把項目遷移到了github,目前版本都是1.3.1 數組

https://github.com/pear/FSM 數據結構

Current Release  
1.3.1 (stable) was released on 2011-02-16 (Changelog)

what? 看起來距今有些年代?不要緊,C語言還在,不少60年代的技術,80年代的技術也至今經典不息。咱們研究的是遠古力量,心裏要平靜,不要有私心雜念。 編輯器

下載後解開包看看。首先要看docs\guide.txt,請用能區分換行的文本編輯器看,好比notepad++。 ide

這段英文主要說了這麼回事情:


Building a Finite State Machine
===============================

The first step in building a Finite State Machine involves listing the finite
set of states.  Then, all of the permissible transitions between these states
must be defined.  A symbol and an optional callback function are associated
with each transition.  The input processing routine will attempt to match its
current symbol against the list of registered transitions.  If a transition
from the current state using that symbol is found, the machine will move to
the new state specified by the transition and, if one has been specified, the
associated callback function will be invoked.

這玩意咋用? 首先要弄出個帶點起碼狀態的狀態機。而後定義容許的狀態轉換方式。用符號+回調函數方式來定義轉換。 定義好之後, 輸入的信息就會通過符號的匹配來對應的轉換。(強心針:暈了? 看看這句 $state=$arr['mySymbol']; 這樣就是一種簡單的符號-狀態匹配,固然本文裏實現的更復雜點點,不過也是經過數組查詢來調用對應函數) 若是輸入的符號,對應當前狀態能夠轉換到別的狀態,就轉狀態;有指明對應狀態轉換對應的回調函數就調用這個函數。

(強心針2: 又暈了? 說白就是這麼回事。假如你臉朝向是個狀態,如今向左(狀態1)看着本身的屏幕。給本身下了死命令,除非右邊來美女(符號)不然不扭頭(狀態轉換)。而後右邊來了個男的(符號),死命令查找不到這個性取向,不扭頭。來了個美女(符號),查詢死命令有這個狀態轉換,則扭頭(狀態轉換),而且調用定義好的回調函數(打招呼,吹口哨,耍流氓……自便)


Creating a New FSM Object
-------------------------
Start by including the FSM package in your script::

下面是怎麼用這個玩意的具體實戰。第一步,php require會用?下面這句是php的,把fsm.php require進來。


    require 'FSM.php';

When constructing a new FSM object, you must specify the machine's initial
state and provide a payload variable.  The payload will be passed to all of
the callback functions, supplying them with state information without
(ab)using global variables.

而後new 個FSM 對象出來,這new不能隨便亂new, 脖子朝向不能null是吧? 得new出來個初始狀態和負載變量。

負載變量用來把狀態信息傳遞給全部回調函數,而且不用全局變量。說白了,看人用本身眼睛看,不要藉助其餘人的目光。

In this example, we pass an array representing a stack as the payload.  The
machine's initial state is set to ``START``.

下面來個例子,弄個數組當負載變量,初始化狀態爲「開始」
::

    $stack = array();
    $fsm = new FSM('START', $stack);

如此簡易的php代碼看起來蠻輕鬆的。


Defining Transitions

--------------------
We'll need to define some transitions in order to make our machine useful.
Let's assume our machine has two additional states: ``MIDDLE`` and ``END``.
Here's how we would define transitions to move us from ``START`` to ``MIDDLE``
and from ``MIDDLE`` to ``END``::

接着來定義狀態轉換

爲了讓狀態機能用,接下來咱們須要定義狀態轉換條件。咱們增長兩個狀態:「中間過程」和「結束」

下面是怎樣定義從「開始」到「中間過程」,和從「中間過程」到「結束」:(張信哲的《從開始到如今》是狀態機)

    function FirstCallback($symbol, $payload)
    {
        echo "First Transition\n";
    }

    function SecondCallback($symbol, $payload)
    {
        echo "Second Transition\n";
    }

    $fsm->addTransition('FIRST', 'START', 'MIDDLE', 'FirstCallback');
    $fsm->addTransition('SECOND', 'MIDDLE', 'END', 'SecondCallback');

從代碼和上面說到的要作的事情,能夠猜到

addTransition的參數,第2,3就是表示從哪一個狀態到哪一個狀態。第4個參數是回調函數名字。


Our machine is now aware of three states (``START``, ``MIDDLE``, and ``END``)
and two symbols (``FIRST`` and ``SECOND``).  Two transitions (``START`` to
``MIDDLE`` and ``MIDDLE`` to ``END``) have been defined and associated with
callbacks.  The following code will process the symbols ``FIRST`` and
``SECOND`` and move us from our initial state (``START``) through the
``MIDDLE`` state to the ``END`` state.

如今咱們的狀態機有了3個狀態(開始,中間過程,結束),2個符號(FIREST和SECEND),2個狀態轉換(開始->中間過程,中間過程->結束),而且有了狀態轉換對應的回調函數。接下來是過程轉換實例:


::

    $fsm->process('FIRST');
    $fsm->process('SECOND');

The processing routine will invoke our two callbacks along the way, as well,
resulting in the following being printed::


    First Transition
    Second Transition

這樣就是前後執行了從開始到中間過程,從中間過程到結束兩個過程的轉換。


Setting Default Transitions
---------------------------
Now we'll set up a default transition.  This transition will be used whenever
the processing routine cannot find a better match for the current state and
symbol.  For our example, we'll consider this an error and print a warning for
the user.

指定默認轉換

如今咱們來設定個默認轉換。默認轉換用來在符號匹配不了時調用(switch..case..default 懂?)。在咱們例子裏

默認認爲是默認轉換會出發錯誤,而且輸出警告給用戶。


::

    function ErrorCallback($symbol, $payload)
    {
        echo "This symbol does not compute: $symbol\n";
    }

    $fsm->setDefaultTransition('START', 'ErrorCallback');

Now let's process our symbols in an unexcepted order::

    $fsm->process('SECOND');
    $fsm->process('FIRST');

Because the ``SECOND`` transition doesn't specify ``START`` as its initial
state, the default transition will be used and the error callback will be
invoked.  The ``FIRST`` transition will work as expected, however, because the
machine will still be in the ``START`` state.

這樣一來,由於在開始狀態下,沒有定義SECOND對應的從開始狀態到其餘狀態的轉換,因此就報錯了。接下來因爲狀態迴歸了「開始」,因此調用「FIRST」符號對應轉換是能夠定期望工做的。


Plotting a State Machine
========================

The FSM package optionally supports the ability to plot a machine's states
with the help of the `Image_GraphViz`_ package.  Doing so is as simple as
creating a new ``FSM_GraphViz`` object using an existing state machine
instance and then exporting the graph.

::

接下來是狀態可視化工做。這個FSM包支持用"Image_GraphViz"包來輸出狀態機狀況。只要new個FSM_GraphViz對象出來而後調用其實例的export就能夠輸出個圖來看看了。


    require_once 'FSM/GraphViz.php';
    $converter = new FSM_GraphViz($fsm);
    $graph = $converter->export();

The resulting graph object is an ``Image_GraphViz`` instance.  To export the
graph as an image, use the ``image()`` method::

    $graph->image('png');

This will produce an image similar to the following:

.. figure:: graphviz.png
   :alt: Example State Machine Plot

Consult the `Image_GraphViz documentation`_ for additional usage information.

.. _Image_GraphViz: http://pear.php.net/package/Image_GraphViz
.. _Image_GraphViz documentation: http://pear.php.net/package/Image_GraphViz/docs


下面是聯繫方式,有想和做者聯繫的請自便。


Development and Support
=======================

Reporting Problems and Suggestions
----------------------------------
If you run into a problem or would like to make a suggestion, please use the
`PEAR Bug Tracker`_.  Feel free to contact me directly for other issues, but
please try to use the bug tracker whenever possible so that others in the
community will benefit from your feedback and my responses.

- `Open Bugs`_
- `Report a New Bug`_

.. _PEAR Bug Tracker: http://pear.php.net/bugs/
.. _Open Bugs: http://pear.php.net/package/FSM/bugs
.. _Report a New Bug: http://pear.php.net/bugs/report.php?package=FSM

Coming Soon
-----------
This section contains a list of "todo" items that will hopefully be addressed
in future releases.

- *No items at this time.*

If you have feature suggestions, please submit them using the `PEAR Bug
Tracker`_.

.. vim: syntax=rst tabstop=4 shiftwidth=4 softtabstop=4 expandtab textwidth=78:

接下來,來玩玩例子。

相關文章
相關標籤/搜索