分享

GoF设计模式之二十 State- -

 wtf_soft 2005-07-22

 

                                      

    C8) State(状态模式)
    定义:当对象的内部状态发生变化时,允许该对象改变其行为。对象看似换了一个类。
    从前面的中介模式到观察者模式到现在的这个状态模式,一直都以对象的内部状态变化为出发点来考虑对对象行为的重新构造,就这点来看,行为模式是以(对象类的)不变应(对象内部状态的)万变,确实非常巧妙。
    接下来看看这个模式,我们在一个内部状态发生改变的时候,通常使用if...elseif...或者switch...case的分支语句加以判断,再将对应的不同行为表现出来,但这只适合简单的线性的变化,如果遇到非线性的场合,用分支语句就显得捉襟见肘了。状态模式从此孕育而生,将状态变化部分从原有对象中分离出来,并让状态自己掌握向下一个状态的变换的过程,从而使得原来的对象可以不用关心对其的控制问题。状态变化越是复杂,这个模式的优点越是明显,Gof举了TCP状态的例子,可惜对TCP还不太了解,所以这里避重就轻,来个简单的例子。
    游戏应该都玩过,无非是赚经验升级,现在就拿这个来说明。一个角色,有一定经验后可以转职升级,不同职业附加值不同,追加能力也不同,其他牵涉的属性也可能不一样。假设从无职业到战士到剑士最后到骑士(似乎老土了点),这样一个过程,职业就是状态,职业的改变影响了角色也就是对象的行为(能力值、攻击方式等等)。定义职业的抽象类和具体实现:
    public interface Career {
        public int ATK;
        public int DEF;
        public int HIT;
        public void Transfer(Role role);
    }
    public class Soldier implements Career {
        public Soldier() {
            ATK = 10;
            DEF = 10;
            HIT = 5;
        }
        public void Transfer(Role role) {
            role.addAttack(this.ATK);
            role.addDefense(this.DEF);
            role.addHit(this.HIT);
            role.setCareer(new Swordman());
        }
    }
    public class Swordman implements Career {
        public Swordman() {
            ATK = 25;
            DEF = 15;
            HIT = 10;
        }
        public void Transfer(Role role) {
            role.addAttack(this.ATK);
            role.addDefense(this.DEF);
            role.addHit(this.HIT);
            role.setCareer(Knight());
        }
    }
    public class Knight implements Career {
        public Knight() {
            ATK = 40;
            DEF = 40;
            HIT = 15;
        }
        public void Transfer(Role role) {
            role.addAttack(this.ATK);
            role.addDefense(this.DEF);
            role.addHit(this.HIT);
        }
    }

    对角色对象的描述:
    public class Role {
        private int attack = 30;
        private int defense = 20;
        private int hit = 60;
        private Career career;
        public Role() {
            setCareer(new Soldier());
        }
        public void setCareer(Career career) {
            this.career = career;
        }
        public void LevelUp() {
            career.Transfer(this);
        }
    }

    得到的客户端的调用
    Role player = new Role();
    player.GainExp();
    player.LevelUp(); //now is Soldierman
    player.GainExp();
    player.LevelUp(); //now is Swordman

    上面只是简单的,用通常的方法也可以,但是如果职业变化复杂了(日系游戏的职业系统非常变态),用if...else...写到最后可能连自己都分不清了。上面的代码还有很多冗余部分,可以用外观模式加以改进,变得更为简练。


   参考:
1、 http://www./designpatterns/designpattern_State.htm(中文、java实例)
2、 http://www./Patterns/PatternState.aspx(英文、C#实例、UML)
3、 http://www.caterpillar./PmWiki/pmwiki.php/DesignPattern/StatePattern(中文、java实例、UML)推荐

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多