17_状态模式
状态模式是一种行为型设计模式,它允许一个对象在其内部状态改变时改变其行为。状态模式将对象的行为封装在不同的状态类中,通过改变状态类来改变对象的行为。
状态模式有三个主要角色:
-
环境类(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(); }