简体   繁体   English

实现状态模式

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM