读书人

Design Pattern: State 形式

发布时间: 2012-09-20 09:36:50 作者: rapoo

Design Pattern: State 模式

如果您不了解TCP的连线方式,在看

?

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


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

IState.java
public interface IState {     public void switchFire(FireSwitch sw); } 

?

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

?

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

?

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连线之间的状态转换的。

读书人网 >软件架构设计

热点推荐