设计模式-状态模式(State)

9 篇文章 0 订阅
9 篇文章 0 订阅
本文介绍了设计模式中的状态模式,它允许一个对象的行为根据其内部状态改变。状态模式通过将状态相关的行为封装在具体状态类中,减少了Context类中的条件判断,提高了代码的可读性和可维护性。示例代码展示了如何在Unity环境中运用状态模式,通过一个值来切换不同状态,并演示了状态转换的过程。
摘要由CSDN通过智能技术生成

设计模式-状态模式(State)

定义

“让一个对象的行为随着内部状态的改变而变化,而该对象也像是换了类一样”

实现

类图

State
+Handle()
ConcreteStateA
+Handle()
ConcreteStateB
+Handle()
ConcreteStateC
+Handle()
Context
+Request()
说明
  • Context(状态拥有者)
    具有“状态”属性的类,可以让外界能够得知状态的改变或通过操作让状态改变;
  • State(状态接口类)
    定义状态的接口,负责规范Context在特定状态下的表现行为;
  • ConcreteStateX(具体状态类)
    继承自状态类,表示Context状态拥有者所包含的状态;

状态转换有两种方式,

  1. 交由Context本身,按条件在各状态之间转换;
  2. 产生Context对象是,指定一个初始状态,而在后续执行过程中的状态转换则交由State对象负责,Context不再介入;

代码

以下代码在unity环境下编写运行

using System.Collections.Generic;
using UnityEngine;

namespace ZhhDesignPattern
{
    //此例通过一个值value来确定状态,
    //状态A:value > 0 && value <= 5;
    //状态B:value > 5 && value <= 10;
    //状态C:value > 10,
    //状态c添加一个进入条件,以演示状态模式的一个处理优点(不同状态的处理放到对应状态中去),只有当处于状态b时才可以通过value > 10 来进入状态c,而处于其他状态时则无法变更
    public class State_UnitTest : MonoBehaviour
    {
        private Context m_context_test;

        void Awake()
        {
            m_context_test = new Context();
        }

        void Start()
        {
            m_context_test.Request(2);
            Debug.Log(m_context_test.ShowCruuentStateName());
            m_context_test.Request(12);//当前状态并非处于状态b无法转换到状态c
            Debug.Log(m_context_test.ShowCruuentStateName());
            m_context_test.Request(7);
            Debug.Log(m_context_test.ShowCruuentStateName());
            m_context_test.Request(12);//当前状态处于状态b可以转换到状态c
            Debug.Log(m_context_test.ShowCruuentStateName());
        }

    }

    //状态拥有者
    public class Context
    {
        public Context()
        {
            allState = new Dictionary<StateName, State>();
            allState.Add(StateName.State_A, new ConcreteState_A(this));
            allState.Add(StateName.State_B, new ConcreteState_B(this));
            allState.Add(StateName.State_C, new ConcreteState_C(this));
            SetState(allState[StateName.State_A]);//设置一个初始状态
        }

        public State currentState = null;//当前状态

        public Dictionary<StateName, State> allState;//所有状态
		//状态拥有者对状态的请求函数,调用当前状态的处理函数,呈现各自不同的状态行为
        public void Request(int value)
        {
            currentState.Handle(value);
        }

        //设置状态,变更当前状态
        public void SetState(State settingState)
        {
            if (settingState == currentState)
                return;
            currentState = settingState;
        }

        //返回当前状态信息
        public string ShowCruuentStateName()
        {
            if (currentState == null)
                return "当前状态为空";
            return currentState.GetStateName();
        }
    }

    //状态接口类
    public abstract class State
    {
        public State(Context context)
        {
            m_context = context;
        }

        protected Context m_context;//状态拥有者

        public abstract void Handle(int value);//处理函数

        public abstract string GetStateName();

    }

    public class ConcreteState_A : State
    {
        public ConcreteState_A(Context context) : base(context)
        {
        }

        public override string GetStateName()
        {
            return "状态为A";
        }
		//进行状态处理
        public override void Handle(int value)
        {
            if (value > 0 && value <= 5)
            {
                m_context.SetState(m_context.allState[StateName.State_A]);
            }
            else if (value > 5 && value <= 10)
            {
                m_context.SetState(m_context.allState[StateName.State_B]);
            }
        }
    }

    public class ConcreteState_B : State
    {
        public ConcreteState_B(Context context) : base(context)
        {
        }

        public override string GetStateName()
        {
            return "状态为B";
        }

        public override void Handle(int value)
        {
            if (value > 0 && value <= 5)
            {
                m_context.SetState(m_context.allState[StateName.State_A]);
            }
            else if (value > 5 && value <= 10)
            {
                m_context.SetState(m_context.allState[StateName.State_B]);
            }
            //只有处于状态B时,且value>10,才可以转换到c状态
            else if (value > 10)
            {
                m_context.SetState(m_context.allState[StateName.State_C]);
            }
        }
    }

    public class ConcreteState_C : State
    {
        public ConcreteState_C(Context context) : base(context)
        {
        }

        public override string GetStateName()
        {
            return "状态为C";
        }

        public override void Handle(int value)
        {
            if (value > 0 && value <= 5)
            {
                m_context.SetState(m_context.allState[StateName.State_A]);
            }
            else if (value > 5 && value <= 10)
            {
                m_context.SetState(m_context.allState[StateName.State_B]);
            }
        }
    }

    public enum StateName
    {
        State_A,
        State_B,
        State_C,
    }
}

小结

使用状态模式的优点:

  • 减少错误的发生并降低维护难度,不使用switch代码块来进行状态判断,可以减少增加状态后的维护难度
  • 执行状态环境单一化,与每一个状态相关的对象及操作都在一个状态类下,可以清楚了解每一个状态的执行所需要的对象及配合的类

缺点:

  • 如果状态模式应用在有大量状态的系统时,就会出现产生过多的类的情况,此时会伴随这类爆炸的问题
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值