狀態模式是一種行為型設計模式,它允許一個物件在其內部狀態改變時改變其行為。狀態模式將物件的行為封裝在不同的狀態類中,透過改變狀態類來改變物件的行為。
狀態模式有三個主要角色:
-
環境類(Context):定義了一個狀態物件的引用,並在需要的時候呼叫狀態物件的方法。環境類可以根據內部狀態的改變來改變行為。
-
抽象狀態類(State):定義了一個介面或抽象類,用於封裝狀態的共同行為。具體的狀態類應該實現該介面或繼承該抽象類,並實現其方法。
-
具體狀態類(Concrete State):實現了抽象狀態類的介面或抽象方法,提供了具體的行為實現。
狀態模式的工作原理如下:
-
環境類持有一個狀態物件的引用,並在需要的時候呼叫狀態物件的方法。
-
客戶端透過呼叫環境類的方法來改變物件的狀態。
-
環境類根據當前的狀態物件來呼叫相應的方法,實現不同狀態下的行為。
狀態模式的優點包括:
-
將物件的狀態和行為進行了解耦,使得物件的狀態可以獨立於行為變化。
-
可以將複雜的條件判斷語句轉移到狀態類中,提高了程式碼的可讀性和可維護性。
-
可以方便地增加新的狀態類,擴充套件新的行為。
狀態模式適用於以下場景:
-
當一個物件的行為取決於其內部狀態,並且需要在執行時根據狀態改變行為時,可以使用狀態模式。
-
當有大量的條件判斷語句需要根據物件的狀態來選擇不同的行為時,可以使用狀態模式。
總結而言,狀態模式透過將物件的行為封裝在不同的狀態類中,使得物件的行為可以根據內部狀態的改變而改變。它提供了一種簡潔的方式來處理物件的狀態轉換,並將複雜的條件判斷語句轉移到狀態類中,提高了程式碼的可讀性和可維護性。
案例場景:
AOI行業中的PCB板缺陷檢測,順序是:進板,MARK點定位,檢測整板,檢測子板,退板
IContext
public interface IContext { string SubBoard { get; set; } void SetState(IState state); void Request(); }
State
public interface IState { int Flag { get; } void Handle(IContext context); }
Context
/// <summary> /// 主機板 /// </summary> public class Board : IContext { private IState _state; public IState State => _state; public string SubBoard { get ; set ; } public Board(IState state, string subBoard) { _state = state; SubBoard = subBoard; } public void Request() { _state.Handle(this); } public void SetState(IState state) { _state = state; } }
Concrete State
/// <summary> /// 進板 /// </summary> public class EnterState : IState { public int Flag => 1; public void Handle(IContext context) { Console.WriteLine("主機板已進入"); context.SetState(new MarkState()); } }
/// <summary> /// mark定位 /// </summary> public class MarkState : IState { public int Flag => 2; public void Handle(IContext context) { Console.WriteLine("正在進行Mark點定位...."); context.SetState(new WholeState()); } }
/// <summary> /// 整板檢測 /// </summary> public class WholeState : IState { public int Flag => 3; public void Handle(IContext context) { Console.WriteLine("正在進行整板檢測..."); if (context.SubBoard != null) { context.SetState(new ChildState()); } else { context.SetState(new ExitState()); } } }
/// <summary> /// 子板檢測 /// </summary> public class ChildState : IState { public int Flag => 4; public void Handle(IContext context) { Console.WriteLine("正在進行子板檢測..."); context.SetState(new ExitState()); } }
/// <summary> /// 退板 /// </summary> public class ExitState : IState { public int Flag => 5; public void Handle(IContext context) { Console.WriteLine("檢測完畢,正在退板..."); } }
呼叫
internal class Client { public void Start() { Board board = new Board(new EnterState(),"有子板"); while(true) { board.Request(); if(board.State.Flag == 5) { board.Request(); break; } } Console.WriteLine("----------------漂亮的分割線-------------------"); board = new Board(new EnterState(), null); while (true) { board.Request(); if (board.State.Flag == 5) { board.Request(); break; } } } }
static void Main(string[] args) { new Client().Start(); Console.ReadKey(); }