You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

状态机改造方案问询:状态类仅实现部分Context接口方法

解决方案:状态机适配部分操作支持的场景

你的核心问题是经典状态机的全接口约束与实际场景中状态仅支持部分操作的矛盾,导致Context不得不做状态类型检查,违反了状态模式的封装性。以下是三种实用的改造方案,适配游戏内购这类场景:


方案1:接口隔离(ISP)拆分小接口

将原有的单一大接口拆分为多个细粒度的功能接口,每个状态类仅实现自身支持的操作对应的接口。Context通过类型判断封装合法性检查,对外提供安全调用的方法。

示例代码(C#):

// 拆分后的功能接口
public interface IPurchasable
{
    void ProcessPurchase();
}

public interface IPreparable
{
    void PrepareOrder();
}

// Active状态支持购买和准备
public class ActiveState : IPurchasable, IPreparable
{
    public void ProcessPurchase()
    {
        // 执行购买逻辑:扣减货币、生成订单等
    }

    public void PrepareOrder()
    {
        // 执行准备逻辑:锁定库存、通知后端等
    }
}

// Finished状态不支持任何操作
public class FinishedState { }

// 改造后的Context
public class PurchaseContext
{
    private object _currentState;

    public void TryPurchase()
    {
        if (_currentState is IPurchasable purchasable)
        {
            purchasable.ProcessPurchase();
        }
        else
        {
            // 游戏内可替换为弹窗提示、日志记录
            throw new InvalidOperationException("当前状态无法执行购买");
        }
    }

    public void TryPrepare()
    {
        if (_currentState is IPreparable preparable)
        {
            preparable.PrepareOrder();
        }
        else
        {
            throw new InvalidOperationException("当前状态无法执行准备");
        }
    }
}

优势:严格遵循SOLID原则,状态类职责单一,新增操作只需添加新接口,无需修改原有代码。


方案2:抽象基类提供默认实现

定义一个包含所有可能操作的抽象基类,为不支持的操作提供默认实现(如抛出异常或空操作),具体状态类仅重写自身支持的方法。

示例代码(C#):

public abstract class PurchaseState
{
    // 默认实现:抛出不支持操作的异常
    public virtual void ProcessPurchase()
    {
        throw new InvalidOperationException("当前状态不支持购买");
    }

    public virtual void PrepareOrder()
    {
        throw new InvalidOperationException("当前状态不支持准备");
    }

    public virtual void CancelPurchase()
    {
        throw new InvalidOperationException("当前状态不支持取消");
    }
}

// Buying状态仅支持取消操作
public class BuyingState : PurchaseState
{
    public override void CancelPurchase()
    {
        // 执行取消逻辑:退款、解锁库存等
    }
}

// Context回到经典状态机模式
public class PurchaseContext
{
    private PurchaseState _currentState;

    public void ProcessPurchase() => _currentState.ProcessPurchase();
    public void PrepareOrder() => _currentState.PrepareOrder();
    public void CancelPurchase() => _currentState.CancelPurchase();
}

优势:Context代码与经典状态机完全兼容,无需修改外部调用逻辑;状态类只需关注自身支持的操作,无需空实现无关方法。


方案3:命令模式扩展状态操作

将每个操作封装为独立的命令类,状态类维护自身支持的命令字典,Context通过命令名称动态查找并执行操作。这种方案适合游戏这类需求频繁变化的场景。

示例代码(C#):

// 命令接口
public interface IPurchaseCommand
{
    void Execute();
}

// 购买命令实现
public class PurchaseCommand : IPurchaseCommand
{
    private readonly PurchaseContext _context;
    public PurchaseCommand(PurchaseContext context) => _context = context;

    public void Execute()
    {
        // 游戏内具体购买逻辑:扣钻石、发道具、统计埋点等
    }
}

// 基础状态类
public class PurchaseState
{
    protected readonly Dictionary<string, IPurchaseCommand> _supportedCommands = new();

    protected void RegisterCommand(string commandKey, IPurchaseCommand command)
    {
        _supportedCommands[commandKey] = command;
    }

    public bool TryExecuteCommand(string commandKey, out IPurchaseCommand command)
    {
        return _supportedCommands.TryGetValue(commandKey, out command);
    }
}

// Preparing状态支持准备和取消命令
public class PreparingState : PurchaseState
{
    public PreparingState(PurchaseContext context)
    {
        RegisterCommand("Prepare", new PrepareCommand(context));
        RegisterCommand("Cancel", new CancelCommand(context));
    }
}

// Context实现
public class PurchaseContext
{
    private PurchaseState _currentState;

    public void ExecuteCommand(string commandKey)
    {
        if (_currentState.TryExecuteCommand(commandKey, out var command))
        {
            command.Execute();
        }
        else
        {
            // 游戏内提示用户操作无效
            throw new InvalidOperationException($"当前状态不支持{commandKey}操作");
        }
    }
}

优势:灵活性极强,可动态添加/移除状态支持的操作,无需修改状态类的继承结构,适配游戏活动、版本迭代等频繁变化的需求。


方案选择建议

  • 若操作固定、状态职责清晰:优先选择接口隔离方案,代码结构最规范。
  • 若操作不多、想保留经典状态机调用方式:选择抽象基类方案,改造成本最低。
  • 若游戏需求频繁变化、需要动态扩展操作:选择命令模式方案,灵活性最高。

内容的提问来源于stack exchange,提问作者pavdan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:20:35