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