设计模式 之 状态模式//用游戏中的例子解释设计模式

此类型的博客的写作初衷在于,整理自己平时所学的知识,随时欢迎各路大神指正

//绿色字的内容为注释

  • 什么时候使用状态模式/状态模式有什么用?
    官方的说法是,当对象有很明确的状态划分的时候;

        1.一个对象的行为取决于它的状态,并且它必须在运行时刻根据状态改变它的行为。

       2.一个操作中含有庞大的多分支结构,并且这些分支决定于对象的状态。360百科


       如:地下城与勇士中,战斗法师的觉醒技能:变身贝亚娜斗神;如下情况通常会使用状态模式
            当玩家变身为贝亚娜状态之前,战斗法师的前冲攻击(→→+X)是这样的——
战斗法师使用手中的武器敲击敌方的头部;
            当玩家变身为贝亚娜状态之后,变身的战斗法师的前冲攻击(→→+X)是这样的——
战斗法师使用手中矛形的武器突刺对方
    总结来讲就是://这种方法只是此模式的一种用法

        当你希望用户(玩家

        使用相同的操作方式/*都是释放前冲攻击*/调用相同的函数名,但实际会因当前的状态不同,使用的是不同的函数,或者说函数调用的方式不变),

        游戏或者程序会产生不同的操作响应时就可以使用状态模式;

    状态模式的好处

        符合单一指责原则开闭原则迪米特法则最少知道法则
         将所有与某个状态有关的行为放到一个类中,并且可以方便地增加新的状态,只需要改变对象状态即可改变对象的行为。

  • 状态模式的核心写法/如何写一个状态模式?小部分内容参考自《设计模式与游戏完美开发》

               想写一个状态模式的基本框架很简单,我们只需要写三部分(三种类型的类)的内容

                    1、Context状态的拥有者:战斗法师

                    2、IState抽象状态类/抽象状态模板,定义了前冲攻击这个技能,但并不会写出具体的实现方法/*通常是虚方法*/,通常会使用abstract抽象类去写,也可以使用接口Instance,或者普通类class

                    3、继承IState的具体状态类通常有多个 这个类override重写了前冲攻击这个技能的技能效果

                        1)State战斗法师战斗法师使用手中的武器敲击敌方的头部;

                       (2)State贝亚娜斗神(战斗法师使用手中矛形的武器突刺对方;

               这三部分拆分开来讲:

                  Context状态的拥有者只需要写3条内容:

                    1、存放IState类的字段//用来存放当前状态,和下面类似

                    2、SetState(IState)方法//用来设置当前状态,和下面类似/给上面的一条赋值

                    3、Requast()//可以同时写多个这种类型的方法,方法内部,放入对应的状态框架中的方法,像什么Update()方法,Enable()方法等专门给外界调用的方法,是子状态中的方法与外界交流的唯一出口

        public class Context
        {
            /// <summary>
            /// 用来保存当前状态
            /// </summary>
            protected State state;
            /// <summary>
            /// 给外界调用的设置状态方法
            /// </summary>
            /// <param name="state"></param>
            public void SetState(State state)
            {
                this.state = state;
            }
            /// <summary>
            /// 使用状态模式的方法,通过这个可以间接的转换状态
            /// </summary>
            /// <param name="var"></param>
            public void Request(int var)
            {
                state.Headle(var);
            }
        }

                 IState状态的框架也同样有3样东西:

                    1、存放Context类的字段//用来方便子状态使用,和上面类似:如 切换状态

                    2、自身的构造函数//用来给Context赋值,和上面类似/给上面一条赋值

                    3、留给子状态继承并重写的所有抽象方法//和上面一样,也不限于一个方法

        public abstract class State
        {
            /// <summary>
            /// 状态中保存有当前状态的拥有者
            /// </summary>
            protected Context context;
            /// <summary>
            /// 想创建一个State 必须new一个此状态的拥有者,没有拥有者哪来的状态
            /// </summary>
            /// <param name="context"></param>
            public State(Context context)
            {
                this.context = context;
            }
            /// <summary>
            /// 给其他扩展状态设置的此状态执行的操作
            /// </summary>
            /// <param name="var"></param>
            public abstract void Headle(int var);

        }

                子状态只有2个主要任务:

                    1、重写父类方法,实现功能

                    2、切换状态

                    //使用默认构造函数

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

            public override void Headle(int var)
            {
                if (var > 10)
                    context.SetState(new ConcreteStateB(context));
                Debug.Log("ConcreteStateA");

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

            public override void Headle(int var)
            {
                if (var > 40)
                {
                    context.SetState(new ConcreteStateA(context));
                }
                Debug.Log("ConcreteStateB");

            }
        }

  • 写好了状态模式后,又该如何去使用状态模式呢?

            使用状态模式分3

                        1、new一个状态的拥有者出来//连角色都没有,怎么可能让角色有状态

                        2、刚刚new出来的拥有者SetState()设置一个初始状态//创建好了新角色以后,此角色总得有个状态吧,让她站着还是坐着随你便

                        3、使用拥有者中的公有方法来间接调用子状态中的方法

public class StateText : MonoBehaviour {

    void Start()
    {
        UnitTest();
    }

    void UnitTest()
    {
        Context theContext = new Context();//new一个状态的拥有者
        theContext.SetState(new ConcreteStateA(theContext));//设置一个初始状态,这里传入new出的拥有者的目地是,给IState中的Context赋值
        theContext.Request(5);//使用拥有者中的公有方法来间接调用子状态中的方法
        theContext.Request(15);
        theContext.Request(25);
        theContext.Request(35);
        theContext.Request(55);

    }
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值