首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >实现状态模式

实现状态模式
EN

Stack Overflow用户
提问于 2020-10-03 00:08:18
回答 2查看 54关注 0票数 0

我有一个对象,它基于它的属性,将在它的服务层执行不同的操作。

假设它是一个具有以下状态的客户: Registered、RegisteredWithoutContactOnFile和NoRegistration。

这些状态基于对象上设置的属性。因此,它将类似于以下内容:

代码语言:javascript
复制
public class Customer
{
        public Registration Registration {get; set;}
        public string Email {get; set;}
        public int Id {get; set;}
}

然后是CustomerService,它根据输入的内容执行不同的数据库操作,如下所示:

代码语言:javascript
复制
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
}

我基本上想摆脱服务层中的if/else语句,并使其成为我对象中的状态,这样我就可以更容易地测试它。有没有人可以帮我解决这个问题,或者如果我做错了?我会说我对状态模式很感兴趣,因为我一直在为AI代理开发有限状态机,但我觉得它在这里也是有意义的。也许一种策略模式会起作用?简而言之,我只是试图从服务层中提取逻辑,使其更具可测试性……任何有见地的人都会非常感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-10-03 00:58:37

在没有转换和新状态的情况下,您不能拥有状态机。这看起来更像是验证检查。它可以使用模式匹配和switch语句来实现,例如:

代码语言:javascript
复制
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!");
}

可以使用带切换表达式的模式匹配来实现状态机,如this example from the docs

代码语言:javascript
复制
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
};

此表达式使用原始状态、操作和参数来决定新状态

票数 2
EN

Stack Overflow用户

发布于 2020-10-03 00:14:42

呃..。

重构多if或嵌套if语句可以有许多不同的方式,例如,您可以使用模板模式,例如,通过州将您的客户转换为不同类型,然后拥有一个字典,核心业务逻辑成为

代码语言:javascript
复制
handlers[customer.GetType()].Handle(customer) 

另一种方法是不使用if-statement,而是使用(每个状态的)具体类型,然后进行模式匹配。

另一种更有趣的方式是雇佣一个参与者来处理这件事。演员自带一个内置的自然FSM。

您可以做的是发出一条消息,您的处理参与者调用Becomes,该actor进入一种状态,该状态将只处理该状态下的消息。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64174849

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档