一,動(dòng)機(jī)
當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),有時(shí)候我們會(huì)希望它的行為也會(huì)隨著狀態(tài)的改變而改變。
比如一個(gè)人(對(duì)象),沒(méi)錢(qián)的時(shí)候(狀態(tài))晚上只能吃泡面(行為),但是當(dāng)他有錢(qián)了(狀態(tài)發(fā)生改變),那么他就可以大口吃肉了(行為也發(fā)生改變)。
這個(gè)時(shí)候就需要一種方式,在對(duì)象的狀態(tài)發(fā)生改變的時(shí)候也同樣改變它的行為。
State模式就是這樣一種模式,允許一個(gè)對(duì)象在它的內(nèi)部狀態(tài)發(fā)生改變的時(shí)候也改變它的行為,因?yàn)樾袨榉椒ㄗ兊貌煌?,就好像這個(gè)類(lèi)也發(fā)生了改變一樣。
二,介紹
1.參與者
Context 環(huán)境,上下文,定義了用戶(hù)需要調(diào)用的方法,并且維護(hù)了ConcreteState的實(shí)例,該實(shí)例定義了Context的狀態(tài)。
State 狀態(tài),抽象的狀態(tài)類(lèi),用接口定義一個(gè)Context在某種狀態(tài)下的行為。
ConcreteState 具體的狀態(tài)實(shí)現(xiàn)類(lèi),實(shí)現(xiàn)一個(gè)與Context狀態(tài)相關(guān)的行為。
2.協(xié)作關(guān)系
Context 將與狀態(tài)有關(guān)的請(qǐng)求委托給ConcreteState來(lái)處理。
Context 可以將自身作為一個(gè)參數(shù)傳給處理該請(qǐng)求的 ConcreteState 對(duì)象。
Context 是主要的用戶(hù)入口,用戶(hù)只需與Context打交道,而無(wú)需考慮 ConcreteState 。
Context 和 ConcreteState 都可以決定哪個(gè)狀態(tài)是另一個(gè)狀態(tài)的后繼狀態(tài),以及在什么條件下進(jìn)行狀態(tài)轉(zhuǎn)換。

代碼示例
public interface State{
public void eat();
}
public class PoorState implements State{
public void eat() {
System.out.println("吃泡面");
}
}
public class RichState implements State{
public void eat() {
System.out.println("吃山珍海味");
}
}
public class Person {
State state;
public void setState(State state){
this.state = state;
}
public void eat(){
this.state.eat();
}
}
三,使用場(chǎng)景
對(duì)象的行為取決于自身的狀態(tài),并且需要在運(yùn)行時(shí)根據(jù)自身的狀態(tài)來(lái)決定自己的行為。
當(dāng)一個(gè)操作包含多個(gè)條件分支,并且這些分支的條件判斷都取決于對(duì)象的狀態(tài)時(shí),可以使用state模式將分支放入類(lèi)中,使得對(duì)象根據(jù)狀態(tài)的不同調(diào)用不同的方法。
四,效果
1.將與狀態(tài)有關(guān)的行為局部化,將不同狀態(tài)的行為分割開(kāi)。
State模式將所有與某個(gè)狀態(tài)有關(guān)的行為都放到一個(gè)子類(lèi)中,因此可以輕松的通過(guò)定義新的子類(lèi)來(lái)追加新的狀態(tài)和轉(zhuǎn)換。對(duì)于一般的通過(guò)if...else...等條件語(yǔ)句來(lái)控制對(duì)象的行為,會(huì)導(dǎo)致在狀態(tài)很多的情況下,出現(xiàn)大量的條件分支,從而使整個(gè)代碼變得龐大,也更難閱讀和維護(hù)。增加一個(gè)新的狀態(tài)可能會(huì)導(dǎo)致要改變多個(gè)操作。
State 模式解決了這些問(wèn)題,將不同狀態(tài)的行為放到不同的子類(lèi)中,從而減少了分支。但于此同時(shí),為不同的狀態(tài)創(chuàng)建不同的子類(lèi),也會(huì)導(dǎo)致子類(lèi)的數(shù)目變多,而對(duì)于單個(gè)類(lèi)中的代碼不夠緊湊,出現(xiàn)類(lèi)的數(shù)量很多,但是每個(gè)類(lèi)里的代碼邏輯卻很少的情況。
2.使?fàn)顟B(tài)轉(zhuǎn)換顯式化
如果一個(gè)對(duì)象僅通過(guò)內(nèi)部的屬性來(lái)定義狀態(tài)的話(huà),那么狀態(tài)的轉(zhuǎn)換僅表現(xiàn)為變量的賦值,不夠明確,容易發(fā)生狀態(tài)不一致的情況。比如,一個(gè)屬性記錄這個(gè)人是有錢(qián)的,另一個(gè)屬性卻記錄了這個(gè)人只有1元錢(qián),就會(huì)出現(xiàn)狀態(tài)不一致的情況:有錢(qián),卻只有1元錢(qián)。
使用State模式可以避免這個(gè)情況發(fā)生,因?yàn)閷?duì)于Context而言,狀態(tài)的轉(zhuǎn)換是原子的,需要為重新綁定State變量。