《Head First 設計模式》學習筆記——狀態模式

在軟件開發過程中,應用程序可能會根據不同的情況作出不同的處理。最直接的解決方案是將這些所有可能發生的情況全都考慮到。然後使用if... ellse語句來做狀態判斷來進行不同情況的處理。但是對複雜狀態的判斷就顯得“力不從心了”。隨着增加新的狀態或者修改一個狀體(if else(或switch case)語句的增多或者修改)可能會引起很大的修改,而程序的可讀性,擴展性也會變得很弱。維護也會很麻煩。那麼我就考慮只修改自身狀態的模式。————題記

設計模式
狀態模式:允許對象在內部狀態改變時改變他的行爲,對象看起來好像修改了它的類。
這個模式將狀態封裝稱爲獨立的類,並將動作委託到代表當前狀態的對象,我們知道行爲會隨着內部狀態而改變。

設計原則
封裝變化
多用組合,少用繼承
針對接口編程,不針對實現編程
爲交互對象之間松耦合設計而努力
類應該對擴展開發,對修改關閉
依賴抽象,不依賴具體類
只和朋友交談
別找我,我會找你
類應該只有一個改變的理由

要點
狀態模式允許一個對象基於內部狀態而擁有不同的行爲。
和程序狀態機不同,狀態模式用類代表狀態。
策略模式通常會用行爲或算法來配置context類,狀態模式允許context隨着狀態改變而改變行爲,狀態轉變可以由state類或context類控制。
使用狀態模式會導致設計模式中類的數目大量增加。
狀態類可以被多個context共享。

模型匹配
狀態模型          封裝基於狀態的行爲,並將行爲委託到當前狀態
策略模型          將可以互換的行爲封裝起來,然後使用委託的方法,決定使用哪一個行爲。
模板方法模型    由子類決定實現算法的某些步驟

何時使用?
State模式在實際使用中比較多,適合"狀態的切換".因爲我們經常會使用If elseif else 進行狀態切換, 如果針對狀態的這樣判斷切換反覆出現,我們就要聯想到是否可以採取State模式了.
不只是根據狀態,也有根據屬性.如果某個對象的屬性不同,對象的行爲就不一樣,這點在數據庫系統中出現頻率比較高,我們經常會在一個數據表的尾部,加上property屬性含義的字段,用以標識記錄中一些特殊性質的記錄,這種屬性的改變(切換)又是隨時可能發生的,就有可能要使用State.

狀態模式:
//狀態接口
public interface State {
 
	public void insertQuarter();
	public void ejectQuarter();
	public void turnCrank();
	public void dispense();
}


//實現狀態接口
public class NoQuarterState implements State {
    GumballMachine gumballMachine;
 
	//通過構造器,得到糖果機的引用
    public NoQuarterState(GumballMachine gumballMachine) {
        this.gumballMachine = gumballMachine;
    }
 
	public void insertQuarter() {
		System.out.println("You inserted a quarter");
		gumballMachine.setState(gumballMachine.getHasQuarterState());
	}
 
	public void ejectQuarter() {
		System.out.println("You haven't inserted a quarter");
	}
 
	public void turnCrank() {
		System.out.println("You turned, but there's no quarter");
	 }
 
	public void dispense() {
		System.out.println("You need to pay first");
	} 
 
	public String toString() {
		return "waiting for quarter";
	}
}


public class HasQuarterState implements State {
	//添加一個隨機數產生器
	Random randomWinner = new Random(System.currentTimeMillis());
	GumballMachine gumballMachine;
 
	public HasQuarterState(GumballMachine gumballMachine) {
		this.gumballMachine = gumballMachine;
	}
  
	public void insertQuarter() {
		System.out.println("You can't insert another quarter");
	}
 
	public void ejectQuarter() {
		System.out.println("Quarter returned");
		gumballMachine.setState(gumballMachine.getNoQuarterState());
	}
 
	public void turnCrank() {
		System.out.println("You turned...");
		
		//決定這名顧客是否贏了
		int winner = randomWinner.nextInt(10);
		if ((winner == 0) && (gumballMachine.getCount() > 1)) {
			gumballMachine.setState(gumballMachine.getWinnerState());
		} else {
			gumballMachine.setState(gumballMachine.getSoldState());
		}
	}

    public void dispense() {
        System.out.println("No gumball dispensed");
    }
 
	public String toString() {
		return "waiting for turn of crank";
	}
}


//實現糖果機
public class GumballMachine {
	//所有的狀態都在這裏
	State soldOutState;
	State noQuarterState;
	State hasQuarterState;
	State soldState;
	State winnerState;
 
	State state = soldOutState;
	int count = 0;
 
	public GumballMachine(int numberGumballs) {
		//每種狀態創建一個狀態實例
		soldOutState = new SoldOutState(this);
		noQuarterState = new NoQuarterState(this);
		hasQuarterState = new HasQuarterState(this);
		soldState = new SoldState(this);
		winnerState = new WinnerState(this);

		this.count = numberGumballs;
 		if (numberGumballs > 0) {
			state = noQuarterState;
		} 
	}
 
	public void insertQuarter() {
		state.insertQuarter();
	}
 
	public void ejectQuarter() {
		state.ejectQuarter();
	}
 
	public void turnCrank() {
		state.turnCrank();
		state.dispense();
	}

	void setState(State state) {
		this.state = state;
	}
 
	void releaseBall() {
		System.out.println("A gumball comes rolling out the slot...");
		if (count != 0) {
			count = count - 1;
		}
	}
 
	int getCount() {
		return count;
	}
 
	void refill(int count) {
		this.count = count;
		state = noQuarterState;
	}

    public State getState() {
        return state;
    }

    public State getSoldOutState() {
        return soldOutState;
    }

    public State getNoQuarterState() {
        return noQuarterState;
    }

    public State getHasQuarterState() {
        return hasQuarterState;
    }

    public State getSoldState() {
        return soldState;
    }

    public State getWinnerState() {
        return winnerState;
    }
 
	public String toString() {
		StringBuffer result = new StringBuffer();
		result.append("\nMighty Gumball, Inc.");
		result.append("\nJava-enabled Standing Gumball Model #2004");
		result.append("\nInventory: " + count + " gumball");
		if (count != 1) {
			result.append("s");
		}
		result.append("\n");
		result.append("Machine is " + state + "\n");
		return result.toString();
	}
}


package net.dp.state.gumballstatewinner;

public class GumballMachineTestDrive {

	public static void main(String[] args) {
		GumballMachine gumballMachine = 
			new GumballMachine(10);

		System.out.println(gumballMachine);

		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		gumballMachine.insertQuarter();
		gumballMachine.turnCrank();
		
		//再在轉動執行多次
	}
}


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