由简单的开始会比较好理解状态模式的作用,先来看一个例子,如果您有一个只能顺时针转动的瓦斯开关,转动一次的状态为off、 small fire、medium fire与large fire,您如何在程式中控制状态的变化与行为呢?一个最简单的方式就是用if..else或是switch流程来控制,例如:
  • State.java

  • Main.java

这个方法很简单,每个人都会,但如果您的状态变化并不是流水式的变化,而是像TCP连线状态一样,会是一个网络图的时候,用 if...else或switch来写的话,您的程式就会乱的不像话了;来考虑如何让物件控制自己的状态转换与所应表现的行为,这个程式可以这 样改写:
  • IState.java

  • OffState

  • SmallState.java

  • MediumState.java
public class MediumState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println( "large fire" ); 
    } 
}  

  • LargeState.java
public class LargeState implements IState { 
    public void switchFire(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println( "off fire" ); 
    } 
}  

  • FireSwitch.java
public class FireSwitch { 
    private State current;

    public FireSwitch() { 
        current = new OffState(); 
    }

    public void setState(State s) { 
        current = s; 
    }

    public void switchFire() { 
        current.switchFire(this); 
    }
} 

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        FireSwitch fireSwitch = new FireSwitch();
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
        fireSwitch.switchFire(); 
    } 
} 

程式执行结果与上一个例子是一样的,但这次并没有用流程控制来进行状态转换,而由物件自行控制自己的状态,与必须表现的行为,这个方式就是State 模式,将这个例子的 UML 类别结构画出就如下所示:


再进一步考虑开关可以顺时针与逆时针转动,这时如果您仍以if...else或switch来写,就会让流程显示复杂,来看看如何使用状态模式来撰 写: 
  • IState.java
public interface IState { 
    public void switchClockWise(FireSwitch sw); 
    public void switchCountClock(FireSwitch sw); 
}  

  • OffState.java
public class OffState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new SmallState()); 
        System.out.println("small fire"); 
    }

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println("large fire"); 
    } 
}  

  • SmallState.java
public class SmallState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new MediumState()); 
        System.out.println("medium fire"); 
    } 

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println("off fire"); 
    } 
}  

  • MediumState.java
public class MediumState implements IState { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new LargeState()); 
        System.out.println("large fire"); 
    }
 
    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new SmallState()); 
        System.out.println("small fire"); 
    } 
}  

  • LargeState.java
public class LargeState implements State { 
    public void switchClockWise(FireSwitch sw) { 
        sw.setState(new OffState()); 
        System.out.println("off fire"); 
    }

    public void switchCountClock(FireSwitch sw) { 
        sw.setState(new MediumState()); 
        System.out.println("medium fire"); 
    } 
}  

  • FireSwitch.java
public class FireSwitch { 
    private State current;

    public FireSwitch() { 
        current = new OffState(); 
    }

    public void setState(State s) { 
        current = s; 
    }

    public void switchClockWise() { 
        current.switchClockWise(this); 
    }

    public void switchCountClock() { 
       current.switchCountClock(this); 
    } 
}  

  • Main.java
public class Main { 
    public static void main(String[] args) { 
        FireSwitch fireSwitch = new FireSwitch();

        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 
        fireSwitch.switchClockWise(); 

        System.out.println();

        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
        fireSwitch.switchCountClock(); 
    } 
} 

接下来您可以任意的转动开关了,无论是顺时针转动或是逆时针转动,状态的转换都由物件自己来表现,这是双向状态转换下的例子, 如果一个状态可能转换至三个以上的状态,使用State模式就更可以看出它的好处了,就像Gof的TCP连线例子一样,如果您了解TCP连线,可以看看原 书是如何实现TCP连线之间的状态转换的。 

State模式的UML结构图如下: 


posted on 2011-08-09 15:53  Kevin Bing  阅读(164)  评论(0编辑  收藏  举报