如何将 switch 语句重构为灵活的有限状态机
How To Refactor Switch Statement To Flexible Finite State Machine
在制造环境中,对于特定过程,有相当简单的 C# Winforms 桌面应用程序涉及无限循环中基于枚举的状态机 运行,遵循类似于以下的结构(状态名称保持通用举个例子)。
switch(state):
case STATE0:
// code (ui update, business logic, and/or database/device communication)
if (...)
state = STATE1; // goes to next state
break;
case STATE1:
// code (ui update, business logic, and/or database/device communication)
if(...)
state = STATE2; // goes to next state
break;
case STATE2:
// code (ui update, business logic, and/or database/device communication)
if(...)
state = STATE1; // goes back to STATE1
else if (...)
state = STATE3; // goes to next state
break;
case STATE3:
// code (ui update, business logic, and/or database/device communication)
if (...)
state = STATE0; // goes back to STATE0
break;
有很多产品都经过这个过程。产品中有许多状态几乎完全相同(例如 state0)。但是特定于产品的逻辑在中,状态在不同产品之间略有不同。
有没有办法将上面的 switch 语句重构为更简洁、更灵活的有限状态机,它可以解释状态内的变化?
如果你有多个状态,需要根据状态改变行为,那么我们可以使用策略模式结合工厂模式。
首先,我们需要声明状态:
public enum State
{
State_1,
State_2,
State_3,
State_4
}
然后根据状态我们需要选择一些行为。我们可以将行为放在 class 中。我们称之为产品。所以我们需要创建一些抽象class,并将所有重复的逻辑放在这个抽象class中。然后,如果某些 classes 的行为不同或者我们想要添加新的行为,那么我们将创建派生的 classes。通过添加新的 classes 我们保持 Open Closed principle.
public abstract class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string TheSameBehaviorForAllProducts()
{
return "TheSameHehaviorForAllProducts";
}
public virtual string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "TheSameHehaviorForAllProducts";
}
}
和 Product
的 class 派生:
public class Product_A : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
public class Product_B : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
public class Product_C : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
然后我们可以创建一个类似映射器的东西,将 State
映射到 Product
。它也可以被认为是工厂模式:
public class StateToProduct
{
public Dictionary<State, Product> ProductByState = new()
{
{ State.A, new Product_A() },
{ State.B, new Product_B() },
{ State.C, new Product_C() }
};
}
和我们的状态机:
public class StateMachine
{
// Here your logic to get state
public State GetState()
{
return State.A;
}
}
然后我们可以运行这样的大系统:
public class SomeBigSystem
{
public void Run()
{
StateMachine stateMachine = new();
StateToProduct stateToProduct = new();
Product product = stateToProduct.ProductByState[stateMachine.GetState()];
// executing some business logic
product.BehaviorThatCanBeOverridenInDerivedClasses();
}
}
因此,我们创建了可测试的简单 classes,并且我们在此处使用了策略模式。
我强烈建议您阅读有关 SOLID and techniques of refactoring
的内容
在制造环境中,对于特定过程,有相当简单的 C# Winforms 桌面应用程序涉及无限循环中基于枚举的状态机 运行,遵循类似于以下的结构(状态名称保持通用举个例子)。
switch(state):
case STATE0:
// code (ui update, business logic, and/or database/device communication)
if (...)
state = STATE1; // goes to next state
break;
case STATE1:
// code (ui update, business logic, and/or database/device communication)
if(...)
state = STATE2; // goes to next state
break;
case STATE2:
// code (ui update, business logic, and/or database/device communication)
if(...)
state = STATE1; // goes back to STATE1
else if (...)
state = STATE3; // goes to next state
break;
case STATE3:
// code (ui update, business logic, and/or database/device communication)
if (...)
state = STATE0; // goes back to STATE0
break;
有很多产品都经过这个过程。产品中有许多状态几乎完全相同(例如 state0)。但是特定于产品的逻辑在中,状态在不同产品之间略有不同。
有没有办法将上面的 switch 语句重构为更简洁、更灵活的有限状态机,它可以解释状态内的变化?
如果你有多个状态,需要根据状态改变行为,那么我们可以使用策略模式结合工厂模式。
首先,我们需要声明状态:
public enum State
{
State_1,
State_2,
State_3,
State_4
}
然后根据状态我们需要选择一些行为。我们可以将行为放在 class 中。我们称之为产品。所以我们需要创建一些抽象class,并将所有重复的逻辑放在这个抽象class中。然后,如果某些 classes 的行为不同或者我们想要添加新的行为,那么我们将创建派生的 classes。通过添加新的 classes 我们保持 Open Closed principle.
public abstract class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
public string TheSameBehaviorForAllProducts()
{
return "TheSameHehaviorForAllProducts";
}
public virtual string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "TheSameHehaviorForAllProducts";
}
}
和 Product
的 class 派生:
public class Product_A : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
public class Product_B : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
public class Product_C : Product
{
public override string BehaviorThatCanBeOverridenInDerivedClasses()
{
return "New Behavior Here";
}
}
然后我们可以创建一个类似映射器的东西,将 State
映射到 Product
。它也可以被认为是工厂模式:
public class StateToProduct
{
public Dictionary<State, Product> ProductByState = new()
{
{ State.A, new Product_A() },
{ State.B, new Product_B() },
{ State.C, new Product_C() }
};
}
和我们的状态机:
public class StateMachine
{
// Here your logic to get state
public State GetState()
{
return State.A;
}
}
然后我们可以运行这样的大系统:
public class SomeBigSystem
{
public void Run()
{
StateMachine stateMachine = new();
StateToProduct stateToProduct = new();
Product product = stateToProduct.ProductByState[stateMachine.GetState()];
// executing some business logic
product.BehaviorThatCanBeOverridenInDerivedClasses();
}
}
因此,我们创建了可测试的简单 classes,并且我们在此处使用了策略模式。
我强烈建议您阅读有关 SOLID and techniques of refactoring
的内容