close

使用狀態模式有幾個優點

1. 切換狀態使用傳統switch…case…當你判定條件非常多時會讓你的程式碼變得超長,這時不妨考慮將每個狀態判定條件改成一個一個狀態物件,每一種case狀態類別是繼承一個抽象類別State,藉由StateManager類別來決定下一個狀態或是前一個狀態為何。

2. 可以隨時新增(插入)一個新狀態,如果是傳統switch…case…會讓你找老半天符合條件的位置,才能決定插入新的case位置。

3.  狀態模式可以只看你感興趣的狀態類別,修改其下一個狀態或是前一個狀態為何。其他不相干的狀態就不會一直用滑鼠滾輪和眼睛過濾,哈哈...。

 

 

抽象類別: State(狀態)

   1: abstract class State
   2:    {
   3:        protected string info;
   4:        public string Info {
   5:            get { return info; }
   6:            set { info = value; }
   7:        }
   8:        public abstract void NextState(StateManager context);
   9:    }

顯示interface: 用來顯示狀態訊息(info)

   1: interface IDisp
   2:    {
   3:        void ShowInfo(string str);
   4:    }

狀態管理類別: StateManager

1. Line 4: 私有成員:State state,紀錄目前狀態

2. Line 5: 方便顯示狀態於一個Lable實體

3. Line 7~12: StateManager建構子,包含傳入新的狀態(state)和一個label實體

4. Line 13~20: State公開屬性

5. Line 22~33: ShowInfo(string)公開方法,用於顯示狀態訊息

6. Line 34~37: NextState(),切換至下一個狀態

   1: class StateManager:IDisp
   2:   {
   3:       public delegate void dShowInfo(String myString);
   4:       private State state;
   5:       private Label label;
   6:       private dShowInfo showInfo;
   7:       public StateManager(State state, Label label)
   8:       {
   9:           this.state = state;
  10:           this.label = label;
  11:           ShowInfo(string.Format("事件名稱: {0}, 訊息: {1}", this.GetType().Name, state.Info));
  12:       }
  13:       public State State
  14:       {
  15:           get { return state; }
  16:           set {
  17:               state = value;
  18:               ShowInfo(string.Format("事件名稱: {0}, 訊息: {1}", this.GetType().Name, state.Info));
  19:           }
  20:       }
  21:  
  22:       public void ShowInfo(string str)
  23:       {
  24:           if (label.InvokeRequired)
  25:           {
  26:               showInfo = new dShowInfo(ShowInfo);
  27:               label.Invoke(showInfo, new object[] { str });
  28:           }
  29:           else
  30:           {
  31:               label.Text = str;
  32:           }
  33:       }
  34:       public void NextState()
  35:       {
  36:           state.NextState(this);
  37:       }
  38:   }

 

假設一個AOI製程包含下列狀態:

image

進料狀態:   將待測物透過載台放入機台

   1: class LoadState : State
   2:    {
   3:        public LoadState(string info)
   4:        {
   5:            this.Info = info;
   6:        }
   7:        public override void NextState(StateManager stateManager)
   8:        {
   9:            stateManager.State = new PickState("吸料狀態");
  10:        }
  11:    }

吸料狀態:   將待測物透過真空吸嘴取出

   1: class PickState : State
   2:     {
   3:         public PickState(string info)
   4:         {
   5:             this.info = info;
   6:         }
   7:         public override void NextState(StateManager stateManager)
   8:         {
   9:             stateManager.State = new MoveLineScanState("移動至線掃描");
  10:         }
  11:     }

移動至線掃描: 將待測物移動至線掃描CCD

   1: class MoveLineScanState :State
   2:     {
   3:         public MoveLineScanState(string info)
   4:         {
   5:             this.info = info;
   6:         }
   7:         public override void NextState(StateManager stateManager)
   8:         {
   9:             stateManager.State = new PlaceLineScanState("線掃描吹料");
  10:         }
  11:     }

線掃描吹料: 將待測物透過真空吸嘴吹料,拋料至檢測台上

   1: class PlaceLineScanState :State
   2:     {
   3:         public PlaceLineScanState(string info)
   4:         {
   5:             this.info = info;
   6:         }
   7:  
   8:         public override void NextState(StateManager stateManager)
   9:         {
  10:             stateManager.State = new LineScanStartState("線掃描開始");
  11:         }
  12:     }

線掃描開始: 待測物取像

   1: class LineScanStartState :State
   2:    {
   3:        public LineScanStartState(string info)
   4:        {
   5:            this.info = info;
   6:        }
   7:        public override void NextState(StateManager stateManager)
   8:        {
   9:            stateManager.State = new BarcodeReadState("條碼讀取");
  10:        }
  11:    }

條碼讀取:  讀取待測物上的條碼

   1: class BarcodeReadState :State
   2: {
   3:     public BarcodeReadState(string info)
   4:     {
   5:         this.info = info;
   6:     }
   7:     public override void NextState(StateManager stateManager)
   8:     {
   9:         stateManager.State = new UnloadState("出料狀態");
  10:     }
  11: }

出料狀態: 將待測物移出機台

   1: class UnloadState : State
   2:    {
   3:        public UnloadState(string info)
   4:        {
   5:            this.info = info;
   6:        }
   7:        public override void NextState(StateManager stateManager)
   8:        {
   9:            stateManager.State = new LoadState("進料狀態");
  10:        }
  11:    }

 

=============================================================

客戶端測試: 到下一個狀態Next按鈕

image

   1: public partial class Form1 : Form
   2: {
   3:     StateManager stateManager;
   4:     public Form1()
   5:     {
   6:         InitializeComponent();
   7:       
   8:     }
   9:  
  10:     private void button1_Click(object sender, EventArgs e)
  11:     {
  12:         stateManager = new StateManager(new LoadState("吸料狀態"), StateLbl);
  13:         //stateManager.Request();
  14:     }
  15:  
  16:     private void button8_Click(object sender, EventArgs e)
  17:     {
  18:         if (stateManager == null) return;
  19:         stateManager.NextState();
  20:     }
  21:  
  22:     private void button2_Click(object sender, EventArgs e)
  23:     {
  24:         stateManager = new StateManager(new MoveLineScanState("移動至線掃描"), StateLbl);
  25:         //stateManager.Request();
  26:     }
  27:  
  28:     private void button3_Click(object sender, EventArgs e)
  29:     {
  30:         stateManager = new StateManager(new PlaceLineScanState("線掃描吹料"), StateLbl);
  31:         //stateManager.Request();
  32:     }
  33:  
  34:     private void button4_Click(object sender, EventArgs e)
  35:     {
  36:         stateManager = new StateManager(new LineScanStartState("線掃描開始"), StateLbl);
  37:         //stateManager.Request();
  38:     }
  39:  
  40:     private void button5_Click(object sender, EventArgs e)
  41:     {
  42:         stateManager = new StateManager(new BarcodeReadState("條碼讀取"), StateLbl);
  43:         //stateManager.Request();
  44:     }
  45:  
  46:     private void button6_Click(object sender, EventArgs e)
  47:     {
  48:         stateManager = new StateManager(new UnloadState("出料狀態"), StateLbl);
  49:         //stateManager.Request();
  50:     }
  51:  
  52:     private void button7_Click(object sender, EventArgs e)
  53:     {
  54:         stateManager = new StateManager(new LoadState("進料狀態"), StateLbl);
  55:         //stateManager.Request();
  56:     }
  57:  
  58:     private void Form1_Load(object sender, EventArgs e)
  59:     {
  60:  
  61:     }
  62: }

點擊[進料狀態]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕

image

點擊[Next]按鈕,回到一開始狀態囉!

image

回到上一個步驟: Prev按鈕

image

State新增抽象方法PrevState(…)

   1: abstract class State
   2: {
   3:     protected string info;
   4:     public string Info {
   5:         get { return info; }
   6:         set { info = value; }
   7:     }
   8:     public abstract void NextState(StateManager stateManager);
   9:     public abstract void PrevState(StateManager stateManager);
  10: }

StateManage新增PrevState()公開方法

   1: class StateManager:IDisp
   2: {
   3:     public delegate void dShowInfo(String myString);
   4:     private State state;
   5:     private Label label;
   6:     private dShowInfo showInfo;
   7:     public StateManager(State state, Label label)
   8:     {
   9:         this.state = state;
  10:         this.label = label;
  11:         ShowInfo(string.Format("事件名稱: {0}, 訊息: {1}", this.GetType().Name, state.Info));
  12:     }
  13:     public State State
  14:     {
  15:         get { return state; }
  16:         set {
  17:             state = value;
  18:             ShowInfo(string.Format("事件名稱: {0}, 訊息: {1}", this.GetType().Name, state.Info));
  19:         }
  20:     }
  21:  
  22:     public void ShowInfo(string str)
  23:     {
  24:         if (label.InvokeRequired)
  25:         {
  26:             showInfo = new dShowInfo(ShowInfo);
  27:             label.Invoke(showInfo, new object[] { str });
  28:         }
  29:         else
  30:         {
  31:             label.Text = str;
  32:         }
  33:     }
  34:     public void NextState()
  35:     {
  36:         state.NextState(this);
  37:     }
  38:     public void PrevState()
  39:     {
  40:         state.PrevState(this);
  41:     }
  42: }

修改繼承State的子類別,實作對應要回到上一個狀態的目的地

   1: class LoadState : State
   2:    {
   3:        public LoadState(string info)
   4:        {
   5:            this.Info = info;
   6:        }
   7:        public override void NextState(StateManager stateManager)
   8:        {
   9:            stateManager.State = new PickState("吸料狀態");
  10:        }
  11:  
  12:        public override void PrevState(StateManager stateManager)
  13:        {
  14:            stateManager.State = new UnloadState("出料狀態");
  15:        }
  16:    }
  17:    class PickState : State
  18:    {
  19:        public PickState(string info)
  20:        {
  21:            this.info = info;
  22:        }
  23:        public override void NextState(StateManager stateManager)
  24:        {
  25:            stateManager.State = new MoveLineScanState("移動至線掃描");
  26:        }
  27:  
  28:        public override void PrevState(StateManager stateManager)
  29:        {
  30:            stateManager.State = new LoadState("進料狀態");
  31:        }
  32:    }
  33:    class MoveLineScanState :State
  34:    {
  35:        public MoveLineScanState(string info)
  36:        {
  37:            this.info = info;
  38:        }
  39:        public override void NextState(StateManager stateManager)
  40:        {
  41:            stateManager.State = new PlaceLineScanState("線掃描吹料");
  42:        }
  43:  
  44:        public override void PrevState(StateManager stateManager)
  45:        {
  46:            stateManager.State = new PickState("吸料狀態");
  47:        }
  48:    }
  49:    class PlaceLineScanState :State
  50:    {
  51:        public PlaceLineScanState(string info)
  52:        {
  53:            this.info = info;
  54:        }
  55:  
  56:        public override void NextState(StateManager stateManager)
  57:        {
  58:            stateManager.State = new LineScanStartState("線掃描開始");
  59:        }
  60:        public override void PrevState(StateManager stateManager)
  61:        {
  62:            stateManager.State = new MoveLineScanState("移動至線掃描");
  63:        }
  64:    }
  65:    class LineScanStartState :State
  66:    {
  67:        public LineScanStartState(string info)
  68:        {
  69:            this.info = info;
  70:        }
  71:        public override void NextState(StateManager stateManager)
  72:        {
  73:            stateManager.State = new BarcodeReadState("條碼讀取");
  74:        }
  75:  
  76:        public override void PrevState(StateManager stateManager)
  77:        {
  78:            stateManager.State = new PlaceLineScanState("線掃描吹料");
  79:        }
  80:    }
  81:    class BarcodeReadState :State
  82:    {
  83:        public BarcodeReadState(string info)
  84:        {
  85:            this.info = info;
  86:        }
  87:        public override void NextState(StateManager stateManager)
  88:        {
  89:            stateManager.State = new UnloadState("出料狀態");
  90:        }
  91:  
  92:        public override void PrevState(StateManager stateManager)
  93:        {
  94:            stateManager.State = new LineScanStartState("線掃描開始");
  95:        }
  96:    }
  97:    class UnloadState : State
  98:    {
  99:        public UnloadState(string info)
 100:        {
 101:            this.info = info;
 102:        }
 103:        public override void NextState(StateManager stateManager)
 104:        {
 105:            stateManager.State = new LoadState("進料狀態");
 106:        }
 107:  
 108:        public override void PrevState(StateManager stateManager)
 109:        {
 110:            stateManager.State = new BarcodeReadState("條碼讀取");
 111:        }
 112:    }
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 me1237guy 的頭像
    me1237guy

    天天向上

    me1237guy 發表在 痞客邦 留言(0) 人氣()