介紹:狀態模式,又稱狀態對象模式(Pattern of Objects for States),狀態模式是對象的行動模式。狀態模式把所研究的對象的行動包裝在不同的狀態對象里,每個狀態對象都屬于1個抽象狀態類的1個子類。
作用:狀態模式的意圖是根據狀態來分離和選擇行動,讓1個對象在其內部狀態改變的時候,其行動也隨之改變。
場景:有些生存類游戲,比如《饑荒》,在場景中會有很多非1次性互動物品,如樹木,草等,它們會定時枯萎,生長。
就樹而言可以分為下面狀態:生長—結果—滅亡
可能在1個業務中,我們會有很多if—else等。可能原來的邏輯是正確的,但是如果我們在里面增加功能,對邏輯進行修改,就會10分麻煩。這個時候就能夠用狀態模式。
角色 | 作用 |
---|---|
環境(Context) | 也稱上下文,狀態決定它的現狀 |
抽象狀態(State) | 定義1個接口,用以封裝環境(Context)對象的1個特定的狀態所對應的行動 |
具體狀態(ConcreteState) | 每個具體狀態類都實現了環境(Context)的1個狀態所對應的行動 |
環境角色
(樹)保存了1生所有可能經歷的狀態,基因決定了樹木生長和結果最大年齡。
public class Tree {
// 持有1個State類型的對象實例
private TreeState state;
// 保存樹木1生所有的狀態
public Map<String, TreeState> states = new HashMap<String, TreeState>();
public int growSize; // 生長可能時間
public int fruitSize; // 結果可能時間
public int now = 1; // 樹木年齡
public Tree() {
states.put("grow", new GrowState(this));
states.put("fruit", new FruitState(this));
states.put("death", new DeathState(this));
this.state = states.get("grow");
// 如果沒有環境因素,植物生長和結果是由基因決定的,生長最多5年,最多2年結果
Random random =new Random();
growSize =random.nextInt(5);
fruitSize = random.nextInt(2);
}
public void setState(TreeState state) {
this.state = state;
}
public void handle() {
state.handle();
}
}
狀態
public interface TreeState {
public void handle();
}
生長狀態
樹木如果生長到1定年齡,進入結果狀態
public class GrowState implements TreeState {
private Tree tree;
public GrowState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
if (tree.now < tree.growSize) {
System.out.println("植物長大");
tree.now++;
} else {
tree.setState(tree.states.get("fruit"));
}
}
}
結果狀態
如果超過結果年齡,樹木進入死亡狀態
public class FruitState implements TreeState {
private Tree tree;
public FruitState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
if (tree.now < (tree.growSize + tree.fruitSize)) {
System.out.println("植物結果");
tree.now++;
} else {
tree.setState(tree.states.get("death"));
}
}
}
死亡狀態
public class DeathState implements TreeState {
private Tree tree;
public DeathState(Tree tree) {
this.tree = tree;
}
@Override
public void handle() {
System.out.println("植物已死亡");
tree.setState(tree.states.get("death"));
}
}
摹擬生長
某1顆樹的1生
Tree tree = new Tree();
while (true) {
tree.handle();
}
進程
植物長大
植物長大
植物長大
植物結果
植物已死亡
缺點
- 會增加類和對象的個數,如果使用不當會造成邏輯混亂。
- 狀態模式對“開閉原則”的支持其實不太好,增加新的狀態類需要修改那些負責狀態轉換的源代碼
在網上學習其他大神博客的時候看到很多評論,這不是狀態模式是策略模式,或這不是策略模式是狀態模式,不要誤人子弟。但是其實博主是正確的,而那些言語粗魯的人反而是自己無知(讓我10分反感)。狀態模式常常與策略模式相混淆。1個簡單的方法是考察環境角色是不是有明顯的狀態和狀態的過渡。
狀態模式:
狀態模式處理的核心問題是狀態的遷移,由于在對象存在很多狀態情況下,各個狀態之間跳轉和遷移進程都是及其復雜的。在狀態模式中,狀態改變是由對象的內部條件決定,外界只需關心其接口,沒必要關心其狀態對象的創建和轉化。
策略模式:
策略模式的好處在于你可以動態的改變對象的策略行動。策略模式里,采取何種策略由外部條件決定,也就是說使用甚么策略由我們來提供,而策略的具體實現類實現對應算法。比如1種商品,我們可以有很多降價和提價策略,我們只需要定義好各種策略的規則,然后讓商品去履行就好了。
更多模式:http://blog.csdn.net/odeviloo/article/details/52382338
更多源碼:https://github.com/oDevilo/Java-Base