[英]Implementing a state pattern
I have an object that based on it's properties, will perform different operations in it's service layer.我有一个基于它的属性的对象,它将在它的服务层中执行不同的操作。
Let's say it's a customer with the following states: Registered, RegisteredWithoutContactOnFile, and NoRegistration.假设它是一个具有以下状态的客户:Registered、RegisteredWithoutContactOnFile 和 NoRegistration。
These states are based on properties set on the object.这些状态基于对象上设置的属性。 So it would be something like the following:所以它会是这样的:
public class Customer
{
public Registration Registration {get; set;}
public string Email {get; set;}
public int Id {get; set;}
}
Then there would be the CustomerService which does different database operations based on what is entered like such:然后会有 CustomerService 根据输入的内容执行不同的数据库操作,如下所示:
public class CustomerService
{
public void RegisterCustomer(Customer customer)
{
if (customer.Registration != null && customer.Id == 0) //Registered without contact -- insert a new contact into the database
else if (customer.Registration == null && customer.Id == 0) // No registration/contact -- insert both a registration and contact into the database
else if (customer.Registration != null && customer.Id > 0) //Registered and contact on file -- update contact and registration information in the database
}
I basically want to get rid of this if/else statement in the service layer and make it a state in my object so that I can more easily test it.我基本上想摆脱服务层中的这个 if/else 语句,并使其成为我对象中的状态,以便我可以更轻松地测试它。 Can anyone assist with how I would go about this or if I'm going about this the wrong way?任何人都可以帮助我解决这个问题,或者我是否以错误的方式解决这个问题? I will say I am interested in the state pattern as I have been working on Finite State Machines for an AI agent but I feel like it makes sense here as well.我会说我对状态模式很感兴趣,因为我一直在为 AI 代理研究有限状态机,但我觉得它在这里也很有意义。 Perhaps a strategy pattern would work?也许策略模式会奏效? In short, I'm just trying to get the logic out of the service layer to make it more testable... any insight would be greatly appreciated!简而言之,我只是想从服务层中获取逻辑以使其更具可测试性......任何见解将不胜感激!
You can't have a state machine without transitions and new states.你不能拥有没有转换和新状态的状态机。 This looks more like validation checks.这看起来更像是验证检查。 It can be implemented used pattern matching and a switch statement, eg :它可以使用模式匹配和 switch 语句来实现,例如:
switch (customer.Registrarion,customer.Id)
{
case (null,0):
//No Registration, contact:
break;
case (Registration r,0):
//Registered without contact
break;
case (Registration r, _):
//Registered with contact
break;
defaut:
throw new InvalidOperationException("Invalid state!");
}
Pattern matching with switch expressions can be used to implement state machines, like this example from the docs :与 switch 表达式的模式匹配可用于实现状态机,就像文档中的这个例子:
var newState = (state, operation, key.IsValid) switch
{
(State.Opened, Operation.Close, _) => State.Closed,
(State.Opened, Operation.Open, _) => throw new Exception(
"Can't open an opened door"),
(State.Opened, Operation.Lock, true) => State.Locked,
(State.Locked, Operation.Open, true) => State.Opened,
(State.Closed, Operation.Open, false) => State.Locked,
(State.Closed, Operation.Lock, true) => State.Locked,
(State.Closed, Operation.Close, _) => throw new Exception(
"Can't close a closed door"),
_ => state
};
This expression uses the original state, an operation and a parameter to decide the new state此表达式使用原始状态、操作和参数来决定新状态
ugh...啊...
refactor multi-if or nested-if statement can have many different ways, something like you could use a template pattern, ie translate your customer to different type by states, and then have a dictionary of [, ], the core business logic becomes重构 multi-if 或nested-if 语句可以有很多不同的方式,比如你可以使用模板模式,即将你的客户按状态翻译成不同的类型,然后有一个 [, ] 的字典,核心业务逻辑变成
handlers[customer.GetType()].Handle(customer)
another way is instead of using if-statement, you could have concrete type (of each state) and then pattern matching.另一种方法是不使用 if 语句,您可以拥有(每个状态的)具体类型,然后进行模式匹配。
one more interesting way is employing an actor to handle this.一种更有趣的方法是聘请演员来处理这个问题。 An actor comes with a nature built-in FSM.演员带有自然内置的 FSM。
What you can do is issuing a message, your handling actor calls Becomes
, which enters in a state that will only handle the messages under that state.您可以做的是发出一条消息,您的处理actor 会调用Becomes
,它会进入仅处理该状态下的消息的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.