使用狀態模式有幾個優點
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: }
留言列表