使用狀態模式有幾個優點
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製程包含下列狀態:
進料狀態: 將待測物透過載台放入機台
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按鈕
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: }點擊[進料狀態]按鈕
點擊[Next]按鈕
點擊[Next]按鈕
點擊[Next]按鈕
點擊[Next]按鈕
點擊[Next]按鈕
點擊[Next]按鈕
點擊[Next]按鈕,回到一開始狀態囉!
回到上一個步驟: Prev按鈕
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: }










留言列表
