状态模式

来源:互联网 发布:软件开发做什么 编辑:程序博客网 时间:2024/05/24 05:42

今天写个状态机,吧。

先假设我们的角色只有两个状态:攻击状态和受击状态。

一般情况下,我们的代码可能是这样的:

    public enum State    {        Attack,        BeHit,    }    public class Player    {        State state;                public Player()        {            state = State.Attack;        }        public State GetPlayerState()        {            return state;        }        public void SetPlayerState(State state)        {            this.state = state;        }    }    class Program    {        static void Main(string[] args)        {            Player player = new Player();            if(player.GetPlayerState() == State.Attack)            {                //干Attack时的事儿                //....                //当受击时,切换到BeHit状态                player.SetPlayerState(State.BeHit);            }            else if(player.GetPlayerState() == State.BeHit)            {                //干BeHit时的事儿                //....                //当受击结束,切换到Attack状态                player.SetPlayerState(State.Attack);            }        }    }
简单明了,客户根据角色当前的状态,当满足对应条件时,切换到新的状态。

好了,现在让我们为角色添加一个新状态:眩晕状态。

我们先在枚举中添写,然后。。。就是在最后一个else if后面添加一个else if,写上眩晕状态时需要做的事儿。

这还不是最恐怖的,最口怕的是,还要在之前的两个状态里,添加对眩晕状态的条件判断。

当添加的状态足够多。。。太容易出错了。

这是因为客户和每个状态的具体实现耦合在了一起。

下面我们看一个新的结构:

    public interface PlayerState    {        void Attack();        void Behit();    }    public class AttackState : PlayerState    {        Player player;        public AttackState(Player player)        {            this.player = player;        }        public void Attack()        {            //攻击        }        public void Behit()        {            player.SetState(player.GetBeHitState());        }    }    public class BeHitState : PlayerState    {        Player player;        public BeHitState(Player player)        {            this.player = player;        }        public void Attack()        {            player.SetState(player.GetAttackState());        }        public void Behit()        {            //受击        }    }        public class Player    {        PlayerState attackState;        PlayerState beHitState;        PlayerState state;        public Player()        {            attackState = new AttackState(this);            beHitState = new BeHitState(this);            state = attackState;        }        public void Attack()        {            state.Attack();        }        public void BeHit()        {            state.Behit();        }        public PlayerState GetAttackState()        {            return attackState;        }        public PlayerState GetBeHitState()        {            return beHitState;        }        public void SetState(PlayerState state)        {            this.state = state;        }    }
这个结构一个很明显的特点:篇幅长。
一本正经的胡说八道。。

最明显的一个特点:把每个状态封装进一个类!

这种结构,客户不知道也不关心状态机的具体行为,他甚至不知道状态机当前处于什么状态!这样,客户只拥有一个状态实例,他只需要在执行每个行为时,调用状态实力的对应方法就好了,至于状态的细节(当前状态做什么事儿,状态的切换),交给每个状态自己做就好了,客户与状态的实现解耦。

现在,当我们再想要添加一个新的状态时,就可以肆无忌惮,这个状态做好自己该做的就好了,不担心会影响到别的状态,也不会被别的状态影响!

一句话总结状态模式:把每一个状态封装成独立的类。

原创粉丝点击