设计模式 --- 状态模式

状态模式 ​​是一种​​行为型设计模式​​,允许对象在内部状态改变时动态改变其行为​​,使对象的行为看起来像是改变了。该模式通过将状态逻辑拆分为独立类​​,消除复杂的条件分支语句,提升代码的可维护性和扩展性。

状态模式的核心价值​​在于​​解耦状态逻辑与上下文​​,为复杂状态管理提供结构化解决方案。在游戏开发中,它尤其适合管理角色控制、AI行为等动态状态流转场景,但需权衡类膨胀和性能成本。

优点:

  1. ​​消除复杂条件分支:消除大量if-else或switch语句,避免代码臃肿且难以维护,将每个分支独立为一个状态类,通过状态切换取代条件分支。

2.提高扩展性:新增状态无需修改上下文类,只需添加新的状态类即可。

3.职责单一化:每个状态类仅关注自身行为,符合单一职责原则。

4.状态转换显式管理:状态转换条件封装在状态类中,避免分散在代码各处。

5.提高可测试性:每个状态可单独测试,无需依赖其他逻辑。

缺点:

1.类数量增多 :每个状态对应一个类,可能导致类数量过多。(例如10个状态 → 10个类 + 接口 + 上下文类)

优化:

1.​使用 ​​层级状态机​​ 合并相似状态(如 BaseMovementState 派生 Walk/Run)。

2.对简单状态使用 ​​枚举 + 委托​​ 简化实现。

2.Context数据共享 :状态类需访问上下文数据,可能导致过度暴露接口(如Player类需向状态类公开血量、位置等字段)。

优化:

1.将共享数据封装为 ​​上下文接口​​,限制访问权限。

2.通过事件/委托通信,减少直接依赖。

3.性能开销 :频繁创建/销毁状态对象可能影响性能(如每帧切换状态)。

优化:

1.使用​​对象池​​复用状态实例。

说明例子:

1.UML类图:

2.实现:

1.定义State的抽象类:

cs 复制代码
    public abstract class State
    {
        protected Context m_Context = null;

        public State(Context _context)
        {
            m_Context = _context;
        }

        public abstract void Handler(int value);
    }

2.定义Context类:

cs 复制代码
    public class Context
    {
        State m_State = null;

        public void Request(int value)
        {
            m_State.Handler(value);
        }

        public void SetState(State state)
        {
            Debug.Log("Context.SetState:" + state);
            m_State = state;
        }
    }

3.定义具体状态类:ConcreteStateA、ConcreteStateB、ConcreteStateC

cs 复制代码
    public class ConcreteStateA : State
    {
        public ConcreteStateA(Context _context) : base(_context)
        {
        }

        public override void Handler(int value)
        {
            Debug.Log("ConcreteStateA.Handler");
            if (value > 10)
            {
                m_Context.SetState(new ConcreateStateB(m_Context));
            }
        }
    }

    public class ConcreateStateB : State
    {
        public ConcreateStateB(Context _context) : base(_context)
        {
        }

        public override void Handler(int value)
        {
            Debug.Log("ConcreteStateB.Handler");
            if (value > 20)
            {
                m_Context.SetState(new ConcreateStateC(m_Context));
            }
        }
    }

    public class ConcreateStateC : State
    {
        public ConcreateStateC(Context _context) : base(_context)
        {
        }

        public override void Handler(int value)
        {
            Debug.Log("ConcreteStateC.Handler");
            if (value > 30)
            {
                m_Context.SetState(new ConcreteStateA(m_Context));
            }
        }
    }

4.测试类:

cs 复制代码
public class StateParttern : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        Context context = new Context();
        context.SetState(new ConcreteStateA(context));
        context.Request(5);
        context.Request(15);
        context.Request(25);
        context.Request(35);
    }
}

游戏中的使用场景:

​​1.角色行为管理​​ :玩家状态 --> 站立、移动、跳跃、攻击、死亡。

​​2.AI决策系统​​ :敌人AI --> 巡逻、追击、攻击、逃跑。

​3.​UI界面切换 ​​:游戏菜单 --> 主界面、设置、背包、暂停。

4.场景切换 :游戏场景 --> 开始场景、大厅场景、战斗场景切换。

​​5.物理交互系统​​:物体状态 --> 静止、运动、碰撞、销毁。

参考书籍:

《Hands-On Game Development Patterns with Unity 2019》

《设计模式与游戏完美开发》

相关推荐
小马爱打代码9 小时前
设计模式:依赖倒转原则 - 依赖抽象,解耦具体实现
设计模式
Koma-forever9 小时前
java设计模式-适配器模式
java·设计模式·适配器模式
自在如风。11 小时前
Java 设计模式:原型模式详解
java·设计模式·原型模式
快乐源泉13 小时前
【设计模式】观察者,只旁观?不,还可随之变化
后端·设计模式·go
浅陌sss15 小时前
设计模式 --- 策略模式
设计模式
FirstMrRight17 小时前
策略模式随笔~
后端·设计模式
NorthCastle18 小时前
设计模式-结构型模式-代理模式
java·设计模式·代理模式
小马爱打代码18 小时前
设计模式:里氏代换原则 - 继承设计的稳定之道
设计模式
快乐源泉20 小时前
【设计模式】桥接,是设计模式?对,其实你用过
后端·设计模式·go
Auroral15620 小时前
创建型模式:抽象工厂模式
设计模式