一、是什麼
1. 定義: 封裝了基于狀态的行為,并使用委托在行為之間切換
2. 好處: 通過将每個狀态封裝到類中,将以後需要做的任何改變局部化
3. 缺點: 使用狀态類通常會導緻設計類的數量大量增加
4. 類圖如上,和政策模式的類圖相同,目的不同,政策是為了封裝互換的行為,用委托來解耦,狀态模式的目的是将狀态封裝成類,用委托來切換狀态
二、示例
場景:假設沖一杯咖啡的步驟是,1. 拿一個空杯子 2. 往杯子中添加速溶咖啡 3. 往杯子中加水
該場景中有三個狀态: 1. 空杯子 2. 裝有速溶咖啡的杯子 2. 裝水的杯子
原來的實作:
寫了個大概的假代碼, 這裡隻有拿杯子的方法,裡面就有了四個if判斷, 後面的方法還是繼續if判斷,相對麻煩一點, 當然最重要的是如果以後要變化步驟的話,整個類都在影響範圍之類。而狀态模式在這裡可以幫我們将變化局部化
final static int NO_CUP = 0 // 還沒有杯子的狀态
final static int EMPTY_CUP = 1 // 空杯
final static int INSTANT_COFFEE_CUP = 2 // 裝有速溶咖啡粉的杯子
final static int ENJOY_CUP = 3 // 沖好咖啡, 美滋滋的杯子
// 拿杯子的方法
public void takeCup() {
if (state == NO_CUP) {
// 此時沒有杯子, 是以我就拿了一個空杯子
state = EMPTY_CUP;
} else if (state == EMPTY_CUP) {
// 已經有一個空杯子了, 不需要再拿了
} else if (state == INSTANT_COFFEE_CUP) {
// 已經有一個裝有速溶咖啡粉的杯子, 不需要再拿了
} else if (state == ENJOY_CUP) {
// 已經沖好咖啡了, 不需要再拿了
}
}
現有的實作:
1. 狀态類
1. 1 狀态類的接口
/**
* 狀态接口
*/
public interface State {
/**
* 1. 拿杯子
*/
void takeCup();
/**
* 2. 往杯子中添加速溶咖啡
*/
void addInstantCoffe();
/**
* 3. 往杯子中加水
*/
void addWater();
/**
* 4. 盡情的享受咖啡
*/
void enjoyCoffe();
}
1.2 沒有杯子的狀态類
/**
* 0. 沒有杯子的狀态
*/
public class NoCupState implements State {
private MakeCoffe makeCoffe;
public NoCupState(MakeCoffe makeCoffe) {
this.makeCoffe = makeCoffe;
}
@Override
public void takeCup() {
makeCoffe.state = makeCoffe.emptyCupState;
System.out.println("拿了一個杯子");
}
@Override
public void addInstantCoffe() {
System.out.println("還沒有一個杯子, 需要拿個杯子");
}
@Override
public void addWater() {
System.out.println("還沒有一個杯子, 需要拿個杯子");
}
@Override
public void enjoyCoffe() {
System.out.println("現在還沒有杯子, 享受不了啊");
}
}
1.3 空杯子的狀态
/**
* 1. 有個空杯子的狀态
*/
public class EmptyCupState implements State {
private MakeCoffe makeCoffe;
public EmptyCupState(MakeCoffe makeCoffe) {
this.makeCoffe = makeCoffe;
}
@Override
public void takeCup() {
System.out.println("已經有個空杯子了, 不需要再");
}
@Override
public void addInstantCoffe() {
this.makeCoffe.state = makeCoffe.instantCoffeCupState;
System.out.println("往杯子加了速溶咖啡");
}
@Override
public void addWater() {
System.out.println("杯子中還需要先加速溶咖啡粉, 再加水");
}
@Override
public void enjoyCoffe() {
System.out.println("現在還是空杯子, 享受不了啊");
}
}
1.4 加了速溶咖啡的狀态
/**
* 2. 加了速溶咖啡的狀态
*/
public class InstantCoffeCupState implements State {
private MakeCoffe makeCoffe;
public InstantCoffeCupState(MakeCoffe makeCoffe) {
this.makeCoffe = makeCoffe;
}
@Override
public void takeCup() {
System.out.println("杯子中已經加了速溶咖啡了, 不需要在拿一個了");
}
@Override
public void addInstantCoffe() {
System.out.println("杯子中已經加了速溶咖啡了, 不需要再放速溶咖啡了");
}
@Override
public void addWater() {
makeCoffe.state = makeCoffe.coffeOkState;
System.out.println("往有速溶咖啡的杯子裡, 加水");
}
@Override
public void enjoyCoffe() {
System.out.println("現在杯子中還沒加水, 享受不了啊");
}
}
1.5 加完水,咖啡沖好的狀态,享受咖啡
/**
* 4. 咖啡沖好, 享受咖啡
*/
public class CoffeOkState implements State {
@Override
public void takeCup() {
System.out.println("咖啡已經沖好了, 不需要再拿一個杯子了");
}
@Override
public void addInstantCoffe() {
System.out.println("咖啡已經沖好了, 不需要再加速溶咖啡了");
}
@Override
public void addWater() {
System.out.println("咖啡已經沖好了, 不需要再加水了");
}
@Override
public void enjoyCoffe() {
System.out.println("享受咖啡咯");
}
}
2. 制作咖啡的類
/**
* 制作咖啡的類
*/
public class MakeCoffe {
/**
* 這杯咖啡的狀态
*/
public State state;
/**
* 沒有杯子狀态
*/
public NoCupState noCupState;
/**
* 有一個空杯子狀态
*/
public EmptyCupState emptyCupState;
/**
* 杯子裡有速溶咖啡粉狀态
*/
public InstantCoffeCupState instantCoffeCupState;
/**
* 沖好咖啡狀态
*/
public CoffeOkState coffeOkState;
public MakeCoffe() {
this.noCupState = new NoCupState(this);
this.emptyCupState = new EmptyCupState(this);
this.instantCoffeCupState = new InstantCoffeCupState(this);
this.coffeOkState = new CoffeOkState();
// 設定預設狀态
this.state = this.noCupState;
}
// 拿杯子
public void takeCup() {
state.takeCup();
}
// 加入速溶咖啡
public void addInstantCoffe() {
state.addInstantCoffe();
}
// 加水
public void addWater() {
state.addWater();
}
public void enjoyCoffe() {
state.enjoyCoffe();
}
}
3. 測試
/**
* 享受咖啡測試類
*/
public class EnjoyCoffeMain {
public static void main(String[] args) {
MakeCoffe makeCoffe = new MakeCoffe();
makeCoffe.takeCup();
makeCoffe.addInstantCoffe();
makeCoffe.addWater();
makeCoffe.enjoyCoffe();
}
}
// 控制台顯示
拿了一個杯子
往杯子加了速溶咖啡
往有速溶咖啡的杯子裡, 加水
享受咖啡咯
1. 恭喜這個程式猿在沒有寫很多IF判斷的情況下,成功享受到咖啡, 狀态模式這裡我覺得好處就是可以将變化分開封裝,以後 要是某個狀态中的操作改了,不需要查找整個IF了,找到對應類修改。
2. 或者以後添加某個狀态的話,如卡布奇諾需要加奶加糖等,就不需要修改IF, 而是添加狀态,修改部分狀态中的代碼
3. 帶來的缺點就是,增加了很多的類
三、總結
想想自己兩年前了解的狀态的模式,現在比以前更了解一點了