软件频道>程序开发>JavaVBVCDelphiC/C++Web开发微软专栏移动数据库程序人生软件工程|开发客
您现在的位置: 天极网 > 开发频道 > 圣斗士星矢的状态模式和观察者模式
全文

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

2008-07-14 08:49作者:来自网络出处:天极网责任编辑:nancy

  星矢:动画片《圣斗士星矢》的男猪脚,超级小强,怎么打也打不死。

  雅典娜:动画片《圣斗士星矢》的女猪脚,自称女神,手下有88个男人为他卖命。

  状态模式:为了方便的控制状态的变化,避免一堆IF/ELSE,以及状态规则改变的时避免代码改动的混乱。

  观察者模式:一个被观察者一动,多个观察者跟着动,经常用于界面UI。

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

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

  以上状态转变用状态模式来表现,一个Saiya类代表星矢,一个SaiyaState代表他的状态,SaiyaState下面有多个子类,分别代表星矢的多种状态,如正常NORMAL、瀕死DYING、小宇宙爆发UNIVERSE、女神护体GODDESS,即把状态抽象成对象,在每种状态里面实现被打的时候所需要更改的状态,这样就避免了每次被打都要进行一次IF/ELSE的判断。

  Java代码 

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 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();
  }

  星矢的状态

  Java代码 


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 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();
  }

  在每种状态里面实现被打的时候所需要更改的状态,例如小宇宙爆发状态下被打

  Java代码

public class UniverseState extends SaiyaState {
  /**
  * @param saiya
  */
  public UniverseState(Saiya saiya) {
  super(saiya);
  }
  /* 小宇宙爆发状态被打进入瀕死状态
  *
  */
  public void hit() {
  saiya.setState( saiya.DYING);
  }
  }
  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,雅典娜就加油。

  Java代码 

public class Athena implements Observer {
  /* 我是雅典娜 我是观察者
  *
  */
  public void update(Observable arg0, Object arg1) {
  System.out.println("雅典娜说:星矢加油啊!!!");
  }
  }
  public class Athena implements Observer {
  /* 我是雅典娜 我是观察者
  *
  */
  public void update(Observable arg0, Object arg1) {
  System.out.println("雅典娜说:星矢加油啊!!!");
  }
  }

  总的来看 这个过程就是这样子:

  Java代码

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());
  }
  }
  }
  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());
  }
  }
  }

  结果星矢在雅典娜的帮助下,有惊无险的战胜了很强的某斗士甲:

  Java代码

  星矢最初的状态是:NormalState

  星矢被揍了1次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:DyingState

  星矢被揍了2次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:UniverseState

  星矢被揍了3次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:DyingState

  星矢被揍了4次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:GoddessState

  星矢被揍了5次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:NormalState

  星矢最初的状态是:NormalState

  星矢被揍了1次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:DyingState

  星矢被揍了2次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:UniverseState

  星矢被揍了3次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:DyingState

  星矢被揍了4次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:GoddessState

  星矢被揍了5次

  雅典娜说:星矢加油啊!!!

  星矢现在的状态是:NormalState

  总结:状态模式的缺点就是会弄出很多子类,如果状态没那么复杂,状态规则改变的可能性比较小的话就不要用了

相关搜索:
关注此文读者还看过
热门关注
特别推荐
文章排行
本周
本月
最近更新
关于我们|About us|网站律师|天极服务|电子杂志|RSS订阅|加入我们|网站地图
TMG
Copyright (C) 1999-2009 Chinabyte.com, All Rights Reserved 版权所有 天极网络
商务联系、网站内容、合作建议:010-82657868
版权声明 在线提交意见反馈 渝ICP证B2-20030003号
经营性网站备案信息 网警备案 中国网站排名
天极传媒:天极网|比特网|IT专家网|IT商网|52PK游戏网|IT分众