Jul 7

圣斗士星矢的状态模式和观察者模式 不指定

星矢:动画片《圣斗士星矢》的男猪脚,超级小强,怎么打也打不死。
雅典娜:动画片《圣斗士星矢》的女猪脚,自称女神,手下有88个男人为他卖命。
状态模式:为了方便的控制状态的变化,避免一堆IF/ELSE,以及状态规则改变的时避免代码改动的混乱。
观察者模式:一个被观察者一动,多个观察者跟着动,经常用于界面UI。

话说星矢和很强的某斗士甲对打,雅典娜在一边看,星矢总是挨揍,每次挨揍完之后星矢的状态总是会发生一些变化:

正常--挨打--瀕死--挨打--小宇宙爆发--挨打--瀕死--挨打--女神护体--挨打(星矢无敌了,打也没用,战斗结束)--正常

以上状态转变用状态模式来表现,一个Saiya类代表星矢,一个SaiyaState代表他的状态,SaiyaState下面有多个子类,分别代表星矢的多种状态,如正常NORMAL、瀕死DYING、小宇宙爆发UNIVERSE、女神护体GODDESS,即把状态抽象成对象,在每种状态里面实现被打的时候所需要更改的状态,这样就避免了每次被打都要进行一次IF/ELSE的判断。
public class Saiya extends Observable {  
    //定义星矢的四种状态  
    public final SaiyaState NORMAL = new NormalState(this);  
  
    public final SaiyaState DYING = new DyingState(this);  
  
    public final SaiyaState GODDESS = new GoddessState(this);  
  
    public final SaiyaState UNIVERSE = new UniverseState(this);  
      
    private SaiyaState state=NORMAL;  
      
    private SaiyaState laststate=null;  
      
    public void hit(){  
        //调用当前状态的被打方法 反过来改变自己的状态  
        state.hit();  
    }  
    public String status(){  
        //当前状态名  
        return state.status();  
    }  
      
    protected void setState(SaiyaState state){  
        laststate=this.state;  
        this.state=state;  
        //观察者模式  
        setChanged();  
        notifyObservers("星矢状态变化");  
    }  
      
    public String getlastStatus(){  
        return laststate.status();  
    }  
}

星矢的状态
public abstract class SaiyaState {  
    protected Saiya saiya;  
  
    public SaiyaState(Saiya saiya) {  
        this.saiya = saiya;  
    }  
      
    public String status(){  
        String name=getClass().getName();  
        return name.substring(name.lastIndexOf(".")+1);  
    }  
    //星矢被打了  
    public abstract void hit();  
}

在每种状态里面实现被打的时候所需要更改的状态,例如小宇宙爆发状态下被打
public class UniverseState extends SaiyaState {  
  
    /**  
     * @param saiya  
     */  
    public UniverseState(Saiya saiya) {  
        super(saiya);  
  
    }  
  
    /* 小宇宙爆发状态被打进入瀕死状态  
     *  
     */  
  
    public void hit() {  
        saiya.setState( saiya.DYING);  
  
    }  
}
  
雅典娜在一边看,星矢每次被打她都要给星矢加油,她是个观察者,星矢是被观察者,这里星矢实现java.util.Observable,每次被打hit就notifyObservers,雅典娜就加油。
public class Athena implements Observer {  
  
    /* 我是雅典娜 我是观察者  
     *  
     */  
    public void update(Observable arg0, Object arg1) {  
        System.out.println("雅典娜说:星矢加油啊!!!");  
        }  
  
}

总的来看 这个过程就是这样子:
public class StateMain {  
    public static void main(String[] args) {  
  
        Saiya saiya = new Saiya();  
        Observer athena = new Athena();  
        saiya.addObserver(athena);  
        System.out.println("星矢最初的状态是:" + saiya.status());  
        for (int i = 0; i < 5; i++) {  
            System.out.println("星矢被揍了" + (i + 1) + "次");  
            saiya.hit();  
            System.out.println("星矢现在的状态是:" + saiya.status());  
        }  
    }  
}  

结果星矢在雅典娜的帮助下,有惊无险的战胜了很强的某斗士甲:
星矢最初的状态是:NormalState  
星矢被揍了1次  
雅典娜说:星矢加油啊!!!  
星矢现在的状态是:DyingState  
星矢被揍了2次  
雅典娜说:星矢加油啊!!!  
星矢现在的状态是:UniverseState  
星矢被揍了3次  
雅典娜说:星矢加油啊!!!  
星矢现在的状态是:DyingState  
星矢被揍了4次  
雅典娜说:星矢加油啊!!!  
星矢现在的状态是:GoddessState  
星矢被揍了5次  
雅典娜说:星矢加油啊!!!  
星矢现在的状态是:NormalState  

总结:状态模式的缺点就是会弄出很多子类,如果状态没那么复杂,状态规则改变的可能性比较小的话就不要用了
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]