其實我覺得很多模式實踐起來真的不難,但是在實踐之前要先知道有這個模式,所以四人幫(Gang of four)幫我們整理出這些模式,真的很有意義,本來以為已經會的東西,再重新看過之後發現,其實還有很多可以實踐在現有的程式碼,或是某些模式以前以為了解了但是其實不夠透測,有些相似的模式一直重複出現的代表是重點呢!
Google首頁的萬聖節遊戲好玩XD快找朋友體驗看看吧!
昨天介紹了外觀模式,在外觀模式(Facade)中可以整理出一個整潔的介面(類別),或是可以把外觀模式當作重構的起點。在狀態模式中,則是固定的運算或動作,在不同的狀態之下會改變,所以將改變後各個狀態的動作封裝起來,客戶端只要改變狀態,即可針對不同的狀態作出正確的行為。
狀態模式 ( State ) ,當一個物件的內在狀態改變時允許改變其行為,這個物件看起來像是改變了其類別。
-- 大話設計模式 p.239
將行為用一個介面封裝起來,針對不同的狀態去改變其行為。
狀態改變的同時行為也改變。
在執行環境( Context )中,只需要改變狀態,而不需要管對應各個狀態時行為的不同。
假設我們儲存的資料是公制,但是要根據顯示的設定切換顯示公制和英制的數值、以及儲存的數值···
狀態的interface
public abstract class State {
//    顯示的數值
    abstract public String tempToDisplay(Double temperture);
    abstract public String vibToDisplay(Double vibration);
//    儲存的數值
    abstract public String tempToSave(Double temperture);
    abstract public String vibToSave(Double vibration);
//    精準到小數點下兩位
    public static String twoDecPlaces(Double value){
        return String.format("%.2f",value);
    }
    public static String saveForm(Double value){
        return String.format("%f",value);
    }
}
公制的State
public class Metric extends State {
    @Override
    public String tempToDisplay(Double temperture) {
        System.out.println("顯示公制");
        return twoDecPlaces(temperture);
    }
    @Override
    public String vibToDisplay(Double vibration) {
        System.out.println("顯示公制");
        return twoDecPlaces(vibration);
    }
    @Override
    public String tempToSave(Double temperture) {
        System.out.println("儲存公制");
        return saveForm(temperture);
    }
    @Override
    public String vibToSave(Double vibration) {
        System.out.println("儲存公制");
        return saveForm(vibration);
    }
}
英制的State
public class British extends State {
//    英制資料儲存成公制
    @Override
    public String tempToDisplay(Double temperture) {
        System.out.println("顯示英制");
        return twoDecPlaces(temperture * 9 / 5 + 32);
    }
    @Override
    public String vibToDisplay(Double vibration) {
        System.out.println("顯示英制");
        return twoDecPlaces(vibration * 25.4);
    }
//    公制資料顯示成英制
    @Override
    public String tempToSave(Double temperture) {
        System.out.println("儲存英制");
        return saveForm((temperture - 32) * 5 / 9);
    }
    @Override
    public String vibToSave(Double vibration) {
        System.out.println("儲存英制");
        return saveForm(vibration/25.4);
    }
}
選擇是哪一種狀態的環境 (Context)
public class MetricSystem {
    private State state;
    public void setState(final State state) {
        this.state = state;
    }
    public void tempView(Double temp){
        System.out.println(state.tempToDisplay(temp));
    }
    public void vibView(Double vib){
        System.out.println(state.vibToDisplay(vib));
    }
    public void tempSave(Double temp){
        System.out.println(state.tempToSave(temp));
    }
    public void vibSave(Double vib){
        System.out.println(state.vibToSave(vib));
    }
}
public class Test {
    @org.junit.jupiter.api.Test
    public void test(){
        MetricSystem metricSystem = new MetricSystem();
        metricSystem.setState(new Metric());
        metricSystem.tempView(50d);
        metricSystem.vibView(10d);
        metricSystem.tempSave(50d);
        metricSystem.vibSave(10d);
        metricSystem.setState(new British());
        metricSystem.tempView(50d);
        metricSystem.vibView(10d);
        metricSystem.tempSave(50d);
        metricSystem.vibSave(10d);
    }
}
測試結果
顯示公制
50.00
顯示公制
10.00
儲存公制
50.000000
儲存公制
10.000000
顯示英制
122.00
顯示英制
254.00
儲存英制
10.000000
儲存英制
0.393701
狀態模式的案例就討論到這邊~如果有什麼更好的例子歡迎留言或私訊我,感恩!