狀態模式
一意圖
一些對象具有多種狀態,而且在不同的狀態下也具有不同的行爲,這些狀態在某些情況下又能夠相互轉換。
爲了在編碼時,對上述的對象能夠好的進行設計和管理,我們可以使用一種被稱之爲狀態模式的設計模式。
狀態模式主要是解決當控制一個對象狀態轉換的條件表達式,過於複雜的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列的類當中,這樣就可以把複雜的判斷邏輯簡化。
二定義
狀態模式允許對象在內部狀態改變時改變它的行爲,對象看起來好像修改了它的類。狀態模式是一種對象行爲型模式。
三類圖
Context(環境類):環境類又稱爲上下文類,它是擁有多種狀態的對象。由於環境類的狀態存在多樣性且在不同狀態下對象的行爲有所不同,因此將狀態獨立出去形成單獨的狀態類。在環境類中維護一個抽象狀態類State的實例,這個實例定義當前狀態,在具體實現時,它是一個State子類的對象。
State(抽象狀態類):它用於定義一個接口以封裝與環境類的一個特定狀態相關的行爲,在抽象狀態類中聲明瞭各種不同狀態對應的方法,而在其子類中實現類這些方法,由於不同狀態下對象的行爲可能不同,因此在不同子類中方法的實現可能存在不同,相同的方法可以寫在抽象狀態類中。
ConcreteState(具體狀態類):它是抽象狀態類的子類,每一個子類實現一個與環境類的一個狀態相關的行爲,每一個具體狀態類對應環境的一個具體狀態,不同的具體狀態類其行爲有所不同。
四代碼示例
自然界中的水,在常溫狀態下(如:27攝氏度)是液態的。當溫度低於0攝氏度時,它會結冰凝固成固態。當溫度大於100攝氏度時,它會蒸發成水蒸氣,變成氣態。
環境類:
public class Water {
private WaterState state; //維持一個對抽象狀態對象的引用
private float temperature = 27;
public Water(){
this.state = new LiquidState(this);
}
//設置狀態對象
public void setState(WaterState state) {
this.state = state;
}
//獲取狀態對象
public WaterState getState() {
return this.state;
}
//設置溫度
public void setTemperature(float temperature){
this.temperature = temperature;
}
//獲取溫度
public float getTemperature(){
return temperature;
}
//升高溫度
public void increaseTemperature(float changeTemperature){
String info = "Current water state is: "+state.stateName+",Water temperature is: "+temperature +". Increase temperature " + changeTemperature;
System.out.println(info);
state.increaseTemperature(changeTemperature);
state.showWaterInfo();
}
//降低溫度
public void reduceTemperature(float changeTemperature){
String info = "Current water state is: "+state.stateName+",Water temperature is: "+temperature +". Reduce temperature " + changeTemperature;
System.out.println(info);
state.reduceTemperature(changeTemperature);
state.showWaterInfo();
}
}
抽象狀態類
public abstract class WaterState {
protected Water water;
protected String stateName;
public abstract void increaseTemperature(float changeTemperature);
public abstract void reduceTemperature(float changeTemperature);
public void showWaterInfo() {
String info = "Water state is: "+stateName+",Water Temperature is: "+water.getTemperature()+" !";
System.out.println(info);
}
}
液態:具體狀態類
public class LiquidState extends WaterState {
public LiquidState(Water water) {
this.water = water;
this.stateName = "Liquid";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
if(temperature > 100){
water.setState(new GasState (water));
}
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
if(temperature < 0){
water.setState(new SolidState (water));
}
}
}
固態:具體狀態類
public class SolidState extends WaterState{
public SolidState(Water water) {
this.water = water;
this.stateName = "Solid";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
if(temperature > 0){
water.setState(new LiquidState (water));
}
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
}
}
氣態:具體狀態類
public class GasState extends WaterState {
public GasState(Water water) {
this.water = water;
this.stateName = "Gas";
}
@Override
public void increaseTemperature(float changeTemperature){
float temperature = this.water.getTemperature() + changeTemperature;
this.water.setTemperature(temperature);
}
@Override
public void reduceTemperature(float changeTemperature){
float temperature = this.water.getTemperature() - changeTemperature;
this.water.setTemperature(temperature);
if(temperature < 100){
this.water.setState(new LiquidState(this.water));
}
else if(temperature < 0){
this.water.setState(new LiquidState(this.water));
}
}
}
測試
public class Test {
public static void main(String args[]) {
Water water = new Water();
water.increaseTemperature(80);
water.increaseTemperature(20);
water.reduceTemperature(60);
water.reduceTemperature(30);
water.reduceTemperature(50);
water.reduceTemperature(60);
}
}
運行結果:
Current water state is: Liquid,Water temperature is: 27.0. Increase temperature 80.0
Water state is: Gas,Water Temperature is: 107.0 !
Current water state is: Gas,Water temperature is: 107.0. Increase temperature 20.0
Water state is: Gas,Water Temperature is: 127.0 !
Current water state is: Gas,Water temperature is: 127.0. Reduce temperature 60.0
Water state is: Liquid,Water Temperature is: 67.0 !
Current water state is: Liquid,Water temperature is: 67.0. Reduce temperature 30.0
Water state is: Liquid,Water Temperature is: 37.0 !
Current water state is: Liquid,Water temperature is: 37.0. Reduce temperature 50.0
Water state is: Solid,Water Temperature is: -13.0 !
Current water state is: Solid,Water temperature is: -13.0. Reduce temperature 60.0
Water state is: Solid,Water Temperature is: -73.0 !
五總結
狀態模式將一個對象在不同狀態下的不同行爲封裝在一個個狀態類中,通過設置不同的狀態對象可以讓環境對象擁有不同的行爲。
當具體業務中出現新的狀態的時候,只需要增加新定義的狀態state子類,而對狀態業務邏輯代碼的修改相對較少,友好的支持了“開閉原則”。
狀態模式可以消除龐大的條件分支語句,使得代碼結構變得簡單清晰,便於修改和擴展。
狀態模式通過把各個狀態的業務邏輯轉移到state子類中,降低了程序的耦合性。