狀態模式是一種行爲型設計模式,它允許一個對象在其內部狀態改變時改變其行爲。狀態模式將對象的行爲封裝在不同的狀態類中,通過改變狀態類來改變對象的行爲。
狀態模式有三個主要角色:
-
環境類(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(); }