17_狀態模式

野码發表於2024-03-14

狀態模式是一種行為型設計模式,它允許一個物件在其內部狀態改變時改變其行為。狀態模式將物件的行為封裝在不同的狀態類中,透過改變狀態類來改變物件的行為。

狀態模式有三個主要角色:

  1. 環境類(Context):定義了一個狀態物件的引用,並在需要的時候呼叫狀態物件的方法。環境類可以根據內部狀態的改變來改變行為。

  2. 抽象狀態類(State):定義了一個介面或抽象類,用於封裝狀態的共同行為。具體的狀態類應該實現該介面或繼承該抽象類,並實現其方法。

  3. 具體狀態類(Concrete State):實現了抽象狀態類的介面或抽象方法,提供了具體的行為實現。

狀態模式的工作原理如下:

  1. 環境類持有一個狀態物件的引用,並在需要的時候呼叫狀態物件的方法。

  2. 客戶端透過呼叫環境類的方法來改變物件的狀態。

  3. 環境類根據當前的狀態物件來呼叫相應的方法,實現不同狀態下的行為。

狀態模式的優點包括:

  1. 將物件的狀態和行為進行了解耦,使得物件的狀態可以獨立於行為變化。

  2. 可以將複雜的條件判斷語句轉移到狀態類中,提高了程式碼的可讀性和可維護性。

  3. 可以方便地增加新的狀態類,擴充套件新的行為。

狀態模式適用於以下場景:

  1. 當一個物件的行為取決於其內部狀態,並且需要在執行時根據狀態改變行為時,可以使用狀態模式。

  2. 當有大量的條件判斷語句需要根據物件的狀態來選擇不同的行為時,可以使用狀態模式。

總結而言,狀態模式透過將物件的行為封裝在不同的狀態類中,使得物件的行為可以根據內部狀態的改變而改變。它提供了一種簡潔的方式來處理物件的狀態轉換,並將複雜的條件判斷語句轉移到狀態類中,提高了程式碼的可讀性和可維護性。

案例場景:

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();
        }

相關文章