状态机不同特性使用举例(使用stateless)

为了使用Stateless库来展示其多种特性,我们可以创建一个简单的示例,该示例涉及用户购物流程的不同状态,包括浏览商品、添加到购物车、结算和完成购买。下面是如何使用C#和Stateless库来实现这一流程的示例代码:

状态定义

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System;  
using Stateless;

public class StateLessTest
{
    private readonly StateMachine<State, Trigger> _machine;

    public StateLessTest()
    {
        _machine = new StateMachine<State, Trigger>(State.Browsing);

        // 设置状态进入和离开时的动作  
        _machine.Configure(State.Browsing)
            .OnEntry(() => Console.WriteLine("开始浏览商品"))
            .OnExit(() => Console.WriteLine("浏览商品结束"));

        _machine.Configure(State.Cart)
            .SubstateOf(State.Browsing) // 继承自Browsing状态  
            .OnEntry(() => Console.WriteLine("商品已添加到购物车"))
            .OnExit(() => Console.WriteLine("离开购物车"));

        _machine.Configure(State.CheckingOut)
            .OnEntry(() => Console.WriteLine("开始结算"))
            .OnExit(() => Console.WriteLine("结算完成"));

        _machine.Configure(State.Completed)
            .OnEntry(() => Console.WriteLine("购买完成"));

        // 定义状态转移  
        _machine.Configure(State.Browsing)
            .Permit(Trigger.AddToCart, State.Cart);
        // 收到Trigger.Checkout命令时,条件转移 true则到下一个状态 
        _machine.Configure(State.Cart)
            .PermitIf(Trigger.Checkout, State.CheckingOut, () => CanCheckout()) 
            .Permit(Trigger.ContinueBrowsing, State.Browsing);//  如果是继续购物,则返回购物流程

        _machine.Configure(State.CheckingOut)
            .Permit(Trigger.CompletePurchase, State.Completed)
            .Ignore(Trigger.Checkout);//或略Trigger.Checkout命令

        // 添加守护条件,防止在不允许的情况下转移状态  
        _machine.OnTransitioned(transition =>
        {
            if (transition.Destination == State.CheckingOut && !CanCheckout())
            {
                throw new InvalidOperationException("无法结算,购物车为空或存在其他问题");
            }
        });
    }

    // 示例方法,用于判断是否可以结算  
    private bool CanCheckout()
    {
        Console.WriteLine("结算判断---有商品并且有钱可以结算");
        // 这里应该有一些逻辑来判断是否可以结算,比如检查购物车是否为空等  
        // 这里我们简单返回true作为示例  
        return true;
    }

    // 触发状态转移的方法  
    public void AddToCart()
    {
        _machine.Fire(Trigger.AddToCart);
    }

    public void Checkout()
    {
        _machine.Fire(Trigger.Checkout);
    }

    public void ContinueBrowsing()
    {
        _machine.Fire(Trigger.ContinueBrowsing);
    }

    public void CompletePurchase()
    {
        _machine.Fire(Trigger.CompletePurchase);
    }

    // 定义状态和触发事件  
    public enum State
    {
        Browsing,
        Cart,
        CheckingOut,
        Completed
    }

    public enum Trigger
    {
        AddToCart,
        Checkout,
        ContinueBrowsing,
        CompletePurchase
    }

    // 示例:查询当前状态  
    public State GetCurrentState()
    {
        return _machine.State;
    }

    // 示例:检查是否可以进行特定转移  
    public bool CanFire(Trigger trigger)
    {
        return _machine.CanFire(trigger);
    }
}

使用测试

// See https://aka.ms/new-console-template for more information

using static StateLessTest;

Console.WriteLine("Hello, World!");
var shoppingMachine = new StateLessTest();
Console.WriteLine("当前状态: " + shoppingMachine.GetCurrentState());
while (true)
{
    var cmd1 = Console.ReadLine();
    if (cmd1 == "1")
    {
        Console.WriteLine("执行命令: AddToCart");
        shoppingMachine.AddToCart();
    }
    else if (cmd1 == "2")
    {
        Console.WriteLine("执行命令: AddToCart");
        shoppingMachine.Checkout();
    }
    else if (cmd1 == "3")
    {
        Console.WriteLine("执行命令: CompletePurchase");
        shoppingMachine.CompletePurchase();
    }
    else
    {
        break;
    }
    // 查询当前状态  
    Console.WriteLine("当前状态: " + shoppingMachine.GetCurrentState());
}


// 查询当前状态  
Console.WriteLine("当前状态: " + shoppingMachine.GetCurrentState());

// 检查是否可以触发某个事件  
Console.WriteLine("是否可以再次添加到购物车: " + shoppingMachine.CanFire(Trigger.AddToCart));

结果显示

在这里插入图片描述

一个打电话的状态机实现

// 配置“Connected”状态下的行为
phoneCall.Configure(State.Connected)
    // 当状态机进入“Connected”状态时,开始计时器
    .OnEntry(t => StartCallTimer())
    // 当状态机离开“Connected”状态时,停止计时器
    .OnExit(t => StopCallTimer())
    // 内部转换:当接收到MuteMicrophone触发器时,执行静音操作
    .InternalTransition(Trigger.MuteMicrophone, t => OnMute())
    // 内部转换:当接收到UnmuteMicrophone触发器时,执行取消静音操作
    .InternalTransition(Trigger.UnmuteMicrophone, t => OnUnmute())
    // 泛型内部转换:当接收到_setVolumeTrigger触发器并携带音量参数时,设置音量
    .InternalTransition<int>(_setVolumeTrigger, (volume, t) => OnSetVolume(volume))
    // 许可转换:当接收到LeftMessage触发器时,转移到“OffHook”状态
    .Permit(Trigger.LeftMessage, State.OffHook)
    // 许可转换:当接收到PlacedOnHold触发器时,转移到“OnHold”状态
    .Permit(Trigger.PlacedOnHold, State.OnHold);

总结

Stateless库中的StateConfiguration<TState, TTrigger>类是用于定义状态机中单个状态配置的核心类,其中TState表示状态类型,TTrigger表示触发器类型。这个类提供了多种方法来描述状态的入口行为、出口行为、内部转换、状态转换以及其他高级配置。下面是StateConfiguration类中一些关键方法的简单说明:
OnEntry(Action entryAction): 定义当状态机进入此状态时执行的操作。entryAction是一个委托,会在状态进入时被调用,TTrigger参数通常是触发这次状态转换的触发器实例,尽管在此委托中可能不会用到。

OnExit(Action exitAction): 定义当状态机离开此状态时执行的操作。exitAction委托在状态退出前执行,同样接收触发离开此状态的触发器实例作为参数。

InternalTransition(TTrigger trigger, Action action): 定义在不改变当前状态的情况下,响应特定触发器trigger执行的操作action。适用于状态内部处理某些事件而不改变状态的情况。

InternalTransition(TTrigger trigger, Action<T, TTrigger> action): 泛型版本的InternalTransition,允许携带一个泛型参数T,这样在内部转换时可以处理额外的数据或上下文信息。

Permit(TTrigger trigger, TState nextState): 设置当接收到特定的trigger时,状态机从当前状态转移到nextState。

PermitIf(TTrigger trigger, TState nextState, Func condition): 类似于Permit,但在转移前会检查一个布尔条件condition,仅当条件为true时才允许转移。

PermitDynamic(TTrigger trigger, Func nextStateSelector): 动态选择下一个状态,nextStateSelector是一个委托,在状态转换时调用以确定目标状态。

Ignore(TTrigger trigger): 指定当状态机处于当前配置的状态时,忽略特定的trigger,不做任何操作也不改变状态。

WithHistoryType(HistoryType historyType): 配置历史类型,决定重新进入带有子状态的状态时,如何恢复到之前的具体子状态。HistoryType可以是None, Shallow, 或 Deep。

SubstateOf(TState superState): 指定当前配置的状态为超级状态superState的子状态,用于构建嵌套状态结构。

Configure(TState subState): 在当前配置的状态内部进一步配置子状态,允许定义嵌套状态的行为。

ConfigureAny(): 配置适用于任何未明确配置状态的行为,常用于定义默认行为。

这些方法共同构成了状态配置的核心,允许开发者详细定义状态机的逻辑和行为。在实际应用中,通过组合使用这些方法,可以构建出复杂且功能丰富的状态机模型。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值