Java設計模式之從[遊戲中的兵種狀態轉換]分析狀態(State)模式
阿新 • • 發佈:2018-12-26
假設我們正在做一個即時戰略遊戲,我們設計一個兵種,他在剛剛生產出來的時候是步兵,但是他可以切換武器,第一次切換會變成弓箭手,第二次切換會變成舉著盾牌的裝甲兵,第三次切換則又變成了步兵……如何實現這個切換的機制?我們一開始會想到,在步兵這個類中加入switch語句,然而這樣的話,程式碼不利於擴充套件,不利於修改,這時我們就可以使用狀態模式了。
狀態模式允許一個物件在其內部狀態改變時改變它的行為。物件看起來似乎修改了它的類。
在本例中,這個兵種有3個狀態——步兵、弓箭手和裝甲兵。我們將這3個狀態都繼承於同一個基類SoldierState,我們還需要定義一個兵種類來包含一個SoldierState物件,以便它是用來儲存這些狀態的,在本例中這個類的名字叫做KnightContext。先看Java程式碼吧:
abstract class SoldierState { public abstract void show(); protected void changeState(KnightContext knight, SoldierState soldierState){ knight.changeState(soldierState); } public abstract void transform(KnightContext knight); } class KnightContext { SoldierState state; public KnightContext(){ state = SwordState.getState(); } public void changeState(SoldierState state){ this.state = state; state.show(); } public void transform(){ state.transform(this); } } class SwordState extends SoldierState{ private static SoldierState state = new SwordState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("現在是步兵模式。"); } public void transform(KnightContext knight) { changeState(knight, BowState.getState()); } } class BowState extends SoldierState{ private static SoldierState state = new BowState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("現在是弓箭模式。"); } public void transform(KnightContext knight) { changeState(knight, ShieldState.getState()); } } class ShieldState extends SoldierState{ private static SoldierState state = new ShieldState(); public static SoldierState getState(){ return state; } public void show() { System.out.println("現在是盾牌模式。"); } public void transform(KnightContext knight) { changeState(knight, SwordState.getState()); } } public class State { public static void main(String[] args) { KnightContext knight = new KnightContext(); knight.transform(); knight.transform(); knight.transform(); knight.transform(); knight.transform(); }
SwordState、BowState、ShieldState為此兵種的三個狀態。KnightContext中有個SoldierState型別的成員state表示這個兵種的當前狀態。請注意,我們並不希望把如何切換的過程寫在KnightContext中(一般的想法可能是,在changeState中加入switch塊,這樣會使得KnightContext過於繁重),而是把如何轉換寫在了SoldierState的transform方法中。這樣就避免了在KnightContext中加入大量的切換狀態的程式碼。如果需要新增加一個狀態,只需要修改和增加SoldierState的子類即可。對於每一個狀態,它都有一個單獨的子類來表示,因此在狀態多的情況下會出現很多個子類,這也是狀態模式的缺點。
程式執行的結果為:
現在是弓箭模式。
現在是盾牌模式。
現在是步兵模式。
現在是弓箭模式。
現在是盾牌模式。
以上便是狀態模式的說明,希望能夠對大家有所幫助。