Java設計模式之狀態模式

一、背景

   最近系統的學習一下Java設計模式,下了2本電子書,《設計模式之禪》與《Head First 設計模式》,支持國產嘛,先看《設計模式之禪》,首先說一下對它的感覺,敘述比較簡潔明瞭,舉例很有趣味性、貼切,吸引人,有很多對比的例子(不採用設計模式和採用設計模式),對初學者來說還不錯。有一個小遺憾就是:作者所畫的類圖有時並沒有和代碼對應。今天看到狀態模式了,突然想來記錄點什麼,所以這篇博文就誕生了。


二、狀態分析

還是拿作者的例子——電梯,電梯有四種動作:開門,關門,運行,停止。對應四種狀態:門敞狀態,門閉狀態,運行狀態,停止狀態,它們之間的關係如下:


開門(open)關門(close)運行(run)停止(stop)
門敞狀態nooknono
門閉狀態oknookok
運行狀態nononook
停止狀態oknookno


三、畫出類圖

纔剛開始學畫類圖了,採用的工具是starUML,如下:

230705271.jpg


四、代碼

在類圖基礎上,利用starUML自動生成代碼,然後再修改而成了。

   1、環境封裝類Context

public class Context {
    private LiftState liftState;
    public LiftState getLiftState() {
        return this.liftState;
    }
                                                                                                                                                                                                    
    public void setListState(LiftState liftState) {
        liftState.setContext(this);
        this.liftState = liftState;
    }
                                                                                                                                                                                                    
    public void open() {
        this.liftState.open();
    }
                                                                                                                                                                                                    
    public void close() {
        this.liftState.close();
    }
                                                                                                                                                                                                    
    public void run() {
        this.liftState.run();
    }
                                                                                                                                                                                                    
    public void stop() {
        this.liftState.stop();
    }
}


   2、狀態抽象類LiftState

public abstract class LiftState {
    protected Context context;
    public void setContext(Context _context) {
        this.context = _context;
    }
                                                                                                                                                                          
    public abstract void open();
                                                                                                                                                                          
    public abstract void close();
                                                                                                                                                                          
    public abstract void run();
                                                                                                                                                                          
    public abstract void stop();
}


   3、四種狀態類和狀態池類OpenningState,ClosingState,RunningState,StoppingState,StatesPools

       (1)OpenningState


public class OpenningState extends LiftState {
    public void open() {
        //已經打開了,不做任何操作
    }
                                                                                                                                                  
    public void close() {
        //打開狀態,是可以關閉的
        System.out.println("關閉電梯...");
        super.context.setListState(StatesPool.closingState);
    }
                                                                                                                                                  
    public void run() {
        //開的時候,當然是不能跑的
    }
                                                                                                                                                  
    public void stop() {
        //開的時候,也沒必要停
    }
}


       (2)ClosingState

public class ClosingState extends LiftState {
    public void open() {
        //關閉了當然是可以打開的
        System.out.println("電梯打開");
        super.context.setListState(StatesPool.openningState);
    }
                                                                                                                                        
    public void close() {
        //已經關閉了
                                                                                                                                        
    }
                                                                                                                                        
    public void run() {
        //關閉當然是可以運行的
        System.out.println("電梯運行");
        super.context.setListState(StatesPool.runningState);
    }
                                                                                                                                        
    public void stop() {
        //關閉也可以停止的
        System.out.println("電梯停止");
        super.context.setListState(StatesPool.stoppingState);
    }
}

       (3)RunningState

public class RunningState extends LiftState {
    public void open() {
        //正在運行的時候不能開
    }
                                                                                                                            
    public void close() {
        //正在運行的時候不能關
    }
                                                                                                                            
    public void run() {
        //已經在運行了
    }
                                                                                                                            
    public void stop() {
        //運行時候,當然是可以停的
        System.out.println("停止電梯...");
        // 改變狀態
        super.context.setListState(StatesPool.stoppingState);
    }
}


       (4)StoppingState

public class StoppingState extends LiftState {
    public void open() {
        //停止狀態下可以打開啦
        System.out.println("電梯打開");
        super.context.setListState(StatesPool.openningState);
    }
                                                                                                                 
    public void close() {
                                                                                                                 
    }
                                                                                                                 
    public void run() {
        //停止狀態下可以繼續運行了
        System.out.println("電梯運行");
        super.context.setListState(StatesPool.runningState);
    }
                                                                                                                 
    public void stop() {
                                                                                                                 
    }
}


       (5)StatesPools

public class StatesPool {
    public static final OpenningState openningState = new OpenningState();
    public static final ClosingState closingState = new ClosingState();
    public static final RunningState runningState = new RunningState();
    public static final StoppingState stoppingState = new StoppingState();
}

   4、客戶端調用類Client


public class Client {
                                                                            
    public static void main(String[] args) {
        Context context = new Context();
        context.setListState(new ClosingState());
                                                                                
        context.open();
        context.close();
        context.run();
        context.stop();
        context.open();
                                                                                
    }
}

   5、運行結果


電梯打開
關閉電梯...
電梯運行
停止電梯...
電梯打開


五、總結

行爲與狀態有對應關係,狀態的切換伴隨着相應的行爲,都可以用狀態模式了。另外抱怨51cto一句:再做好一點行不行啊,每次貼代碼都要我重新選擇語言,上面貼的代碼都選了n次Java了,就不能幫我記住嗎?

ps:代碼地址http://down.51cto.com/data/1029676



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章