有限狀態機編程

1. 概述

    The intent of the STATE pattern is to distribute state-specific logic across classes that represent an object’s state.

    STATE 設計模式的目的 是:將特定狀態相關的邏輯分散到一些類的狀態類中。

 

2. 實例

    旋轉門: Consider the model of the state of a carousel door(revolving door). A carousel is a large, smart rack that accepts material through a doorway and stores the material according to a bar code ID on it. The door operates with a single button. See the state diagram below for some detail.

 

    旋轉門的狀態圖:(狀態圖細節見 4. )


 

3. 狀態模型的兩種實現方法

    3.1 方法一: switch

  

Observable是java.util中的類^^居然以前都不曉得哦,該打!

 

Door的具體實現如下:

Java代碼  收藏代碼
  1. import java.util.Observable;  
  2.   
  3. /** 
  4.  * This class provides an initial model of a carousel door 
  5.  * that manages its state without moving state-specific 
  6.  * logic out to state classes. 
  7.  */  
  8. public class Door extends Observable {  
  9.     public final int CLOSED = -1;  
  10.     public final int OPENING = -2;  
  11.     public final int OPEN = -3;  
  12.     public final int CLOSING = -4;  
  13.     public final int STAYOPEN = -5;  
  14.   
  15.     private int state = CLOSED;  
  16.   
  17.     /** 
  18.      * The carousel user has touched the carousel button. This "one touch" 
  19.      * button elicits different behaviors, depending on the state of the door. 
  20.      */  
  21.     public void touch() {  
  22.         switch (state)  
  23.         {  
  24.             case OPENING:  
  25.             case STAYOPEN:  
  26.                 setState(CLOSING);  
  27.                 break;  
  28.             case CLOSING:  
  29.             case CLOSED:  
  30.                 setState(OPENING);  
  31.                 break;  
  32.             case OPEN:  
  33.                 setState(STAYOPEN);  
  34.                 break;  
  35.             default:  
  36.                 throw new Error("can't happen");  
  37.         }  
  38.     }  
  39.   
  40.     /**  
  41.      * This is a notification from the mechanical carousel that  
  42.      * the door finished opening or shutting. 
  43.      */  
  44.     public void complete() {  
  45.         if (state == OPENING)  
  46.             setState(OPEN);  
  47.         else if (state == CLOSING)  
  48.             setState(CLOSED);  
  49.     }  
  50.   
  51.     /** 
  52.      * This is a notification from the mechanical carousel that the 
  53.      * door got tired of being open. 
  54.      */  
  55.         public void timeout() {  
  56.             setState(CLOSING);  
  57.         }  
  58.        
  59.     /** 
  60.      * @return a textual description of the door's state 
  61.      */  
  62.     public String status()  
  63.     {  
  64.         switch (state)  
  65.         {  
  66.             case OPENING:  
  67.                 return "Opening";  
  68.             case OPEN:  
  69.                 return "Open";  
  70.             case CLOSING:  
  71.                 return "Closing";  
  72.             case STAYOPEN:  
  73.                 return "StayOpen";  
  74.             default:  
  75.                 return "Closed";  
  76.         }  
  77.     }  
  78.   
  79.     private void setState(int state)  
  80.     {  
  81.         this.state = state;  
  82.         setChanged();  
  83.         notifyObservers();  
  84.     }  
  85. }  
 

但是採用這種實現,有一個缺陷:state變量在Door類的實現中渾身擴散,就像癌症一般!

 

    3.2 方法二: State Pattern

 

    A. 基本的 State Pattern 實現


 

    以上設計方式要求每個狀態子類實例內部“ hold 住”一個 Door2 實例的引用,這樣才能完成 Door2 實例和它的各個狀態實例時間的互相通信。這種設計要求一個狀態實例對應一個 Door2 實例,這樣一來,一個狀態實例就只能爲一個 Door2 實例服務

    客戶端這樣調用:

Java代碼  收藏代碼
  1. public static void main(String[] args){  
  2.         Door2 door=new Door2();  
  3.           
  4.         //1. 初始狀態  
  5.         System.out.println(door.status());  
  6.           
  7.         //2. 轉移到Opening狀態  
  8.         door.touch();  
  9.         System.out.println(door.status());  
  10.           
  11.         //3. 轉移到Open狀態  
  12.         door.complete();  
  13.         System.out.println(door.status());  
  14.           
  15.         //4. 轉移到Closing狀態  
  16.         door.timeout();  
  17.         System.out.println(door.status());  
  18.           
  19.         //5. 回到Closed狀態  
  20.         door.complete();  
  21.         System.out.println(door.status());  
  22.     }  

 

下面給出Door2類、DoorState抽象類、DoorStayOpen類的實現:

Door2:

Java代碼  收藏代碼
  1. public class Door2 extends Observable {  
  2.     public final DoorState CLOSED = new DoorClosed(this);  
  3.     public final DoorState CLOSING = new DoorClosing(this);  
  4.     public final DoorState OPEN = new DoorOpen(this);  
  5.     public final DoorState OPENING = new DoorOpening(this);  
  6.     public final DoorState STAYOPEN = new DoorStayOpen(this);  
  7.   
  8.     private DoorState state = CLOSED;  
  9.   
  10.     public void touch() {  
  11.         state.touch();  
  12.     }  
  13.   
  14.     public void complete() {  
  15.         state.complete();  
  16.     }  
  17.   
  18.     public void timeout() {  
  19.         state.timeout();  
  20.     }  
  21.   
  22.     public String status() {  
  23.         return state.status();  
  24.     }  
  25.   
  26.     protected void setState(DoorState state) {  
  27.         this.state = state;  
  28.         setChanged();  
  29.         notifyObservers();  
  30.     }  

 

DoorState抽象類:

Java代碼  收藏代碼
  1. public abstract class DoorState {  
  2.     protected Door2 door;  
  3.   
  4.     public abstract void touch();  
  5.   
  6.     public void complete() {  
  7.     }  
  8.   
  9.     public void timeout() {  
  10.     }  
  11.   
  12.     public String status() {  
  13.         String s = getClass().getName();  
  14.         return s.substring(s.lastIndexOf('.') + 1);  
  15.     }  
  16.   
  17.     public DoorState(Door2 door) {  
  18.         this.door = door;  
  19.     }  
  20. }  
 

DoorStayOpen類:

Java代碼  收藏代碼
  1. public class DoorStayOpen extends DoorState {  
  2.     public DoorStayOpen(Door2 door) {  
  3.         super(door);  
  4.     }  
  5.   
  6.     public void touch() {  
  7.         door.setState(door.CLOSING);  
  8.     }  
  9. }  
 


    B. State Pattern 實現 2 ——讓狀態實例( DoorState 的子類實例)爲多個 Door2 實例服務

    子狀態 DoorOpen 實現轉移時只負責返回下目標狀態是什麼,將狀態轉移的 action 留給 Door2 實例自己來做;而不是像“ A. 基本的 State Pattern 實現”那樣在 DoorOpen 內部保存一個 Door2 實例的引用 door ,親自調用door.setState(door.STAYOPEN); 來實現狀態轉移

    改進後的關鍵代碼:

   

Java代碼  收藏代碼
  1. public class DoorOpen extends DoorState{  
  2.        public DoorState touch(){  
  3.            return DoorState.STAYOPEN;  
  4.            // 以前是 door.setState(door.STAYOPEN);  
  5.        }  
  6.        ...  
  7. }  
  8.   
  9.    
  10.   
  11.     public class Door2 extends Observable{  
  12.        public void touch(){  
  13.            state=state.touch();  
  14.            // 以前是 state.touch();  
  15.            // 即將轉移狀態的工作留給狀態實例來做,事不關己高高掛起  
  16.        }  
  17. }   

 

    C. State Pattern 實現 3 ——讓狀態實例( DoorState 的子類實例)爲多個 Door2 實例服務

    另一種實現這種效果的方法是:將 Door2 實例作爲參數傳遞給 DoorState 的狀態轉移方法,而非建立Composite 的關聯關係(將 DoorState 的子類對象作爲 Door2 的屬性)。

    也即,用“ Dependency 依賴”(弱依賴,如調用)代替了“ Association 關聯”(強依賴,如作爲屬性進行組合)。

 

4. 狀態圖細節

    何謂 State 狀態 : Generally speaking, the state of an object depends on the collective value of the object ’ s instance variables. In some cases, most of an object ’ s attributes are fairly static once set, and one attribute is dynamic and plays a prominent role in the class ’ s logic. This attribute may represent the state of the entire object and may even be named state.



 

    4.1 State

    You can subdivide a state icon into areas that show the state ’ s name and activities活動 .

    3 frequently used categories of activities are entry (what happens when the system enters the state), exit (what happens when the system leaves the state), and do (what happens while the system is in the state).


 

    4.2 Transition s (Details: Event[Guard Condition]/Action)

    You can also add some details to the transition lines. You can indicate an event that causes a transition to occur (atrigger event ) and the computation (the action ) that executes and makes the state change happen.

    A guard condition : when it’s met, the transition takes place. 通常將超時作爲監護條件,∵可以認爲此時沒有任何event.


•源狀態 Source State :即受轉換影響的狀態

•目標狀態 Target State :當轉換完成後,對象的狀態

•觸發事件 (Trigger) Event :用來爲轉換定義一個事件,包括調用、改變、信號、時間四類事件

•監護條件 (Guard Condition) :布爾表達式,決定是否激活轉換、

•動作 (Action) :轉換激活時的操作

 

幾個實例:



 

 





 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章