設計模式 | 狀態模式(state)

定義:

當一個對象的內在狀態改變時容許改變其行爲,這個對象看起來像是改變了其類。

結構:(書中圖,侵刪)

 

一個抽象的狀態類,擁有一個與狀態相關的行爲方法
若干個具體的狀態類
一個上下文類,持有抽象狀態類
 

實例:

寫到這裏,看了一眼桌上的零食,想到了一個例子。
食品大概分爲三個階段,或者說三種狀態:最佳食用期,可食用期(過了最佳食用期,但未過時),已過時。
食品類(包含:最佳食用天數、過時天數、出廠天數):
package designpattern.state;

public class Food {
    private String name;
    private int manufactureDays;// 出廠天數
    private int bestBeforeDays;// 最佳食用天數(從出廠時間算起)
    private int expiryDays;// 保質期天數
    private FoodState foodState;

    public Food(String name, int bestBeforeDays, int expiryDays) {
        this.name = name;
        this.bestBeforeDays = bestBeforeDays;
        this.expiryDays = expiryDays;
        this.foodState = new BestBeforeState();
    }

    public void eat() {
        foodState.reaction(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getManufactureDays() {
        return manufactureDays;
    }

    public void setManufactureDays(int manufactureDays) {
        this.manufactureDays = manufactureDays;
    }

    public int getBestBeforeDays() {
        return bestBeforeDays;
    }

    public void setBestBeforeDays(int bestBeforeDays) {
        this.bestBeforeDays = bestBeforeDays;
    }

    public int getExpiryDays() {
        return expiryDays;
    }

    public void setExpiryDays(int expiryDays) {
        this.expiryDays = expiryDays;
    }

    public FoodState getFoodState() {
        return foodState;
    }

    public void setFoodState(FoodState foodState) {
        this.foodState = foodState;
    }

}
抽象狀態類:
package designpattern.state;

public interface FoodState {
    public void reaction(Food food);
}
具體狀態類:
最佳食用狀態:
package designpattern.state;

public class BestBeforeState implements FoodState {

    @Override
    public void reaction(Food food) {
        if (food.getManufactureDays() <= food.getBestBeforeDays()) {
            System.out.print("第" + food.getManufactureDays() + "天吃,");
            System.out.println("[" + food.getName() + "]在最佳食用期中,好吃~~");
        } else {
            food.setFoodState(new EatableState());
            food.eat();
        }
    }

}
可食用狀態:
package designpattern.state;

public class EatableState implements FoodState {

    @Override
    public void reaction(Food food) {
        if (food.getManufactureDays() <= food.getExpiryDays()) {
            System.out.print("第" + food.getManufactureDays() + "天吃,");
            System.out.println("[" + food.getName() + "]在可食用期中,味道還能夠");
        } else {
            food.setFoodState(new ExpiredState());
            food.eat();
        }
    }

}
已過時狀態:
package designpattern.state;

public class ExpiredState implements FoodState {

    @Override
    public void reaction(Food food) {
        if (food.getManufactureDays() > food.getExpiryDays()) {
            System.out.print("第" + food.getManufactureDays() + "天吃,");
            System.out.println("[" + food.getName() + "]過時了,無法吃了");
        } else {
            food.setFoodState(new EatableState());
            food.eat();
        }
    }

}
客戶端:
package designpattern.state;

public class Client {
    public static void main(String[] args) {
        Food food = new Food("麪包", 1, 7);// 設置最佳食用期1天,保質期7天
        food.setManufactureDays(1);
        food.eat();

        food.setManufactureDays(3);
        food.eat();

        food.setManufactureDays(10);
        food.eat();
    }
}

結果輸出:react

第1天吃,[麪包]在最佳食用期中,好吃~~
第3天吃,[麪包]在可食用期中,味道還能夠
第10天吃,[麪包]過時了,無法吃了

總結:

依舊是爲了解耦的一個設計模式,經過抽象的方式來實現,感受光看代碼的話,不少設計模式其實長得都很像,本質區別只是在應用的場景上。
主要是理解在什麼狀況下應該用哪一個設計模式。
而狀態模式主要是用在,對象的行爲依賴於它的狀態,且狀態間轉換的條件判斷相對比較複雜的狀況,表如今代碼中就是有不少條件判斷分支。
從上面的例子,能夠看出各個狀態間的轉換有一種傳遞的關係,而不是把全部其餘的條件判斷都寫在裏面,這樣能夠保證當前的狀態只關注和本身相關的條件。
相關文章
相關標籤/搜索