5 使用環境類實作狀态轉換
在狀态模式中實作狀态轉換時,具體狀态類可通過調用環境類Context的setState()方法進行狀态的轉換操作,也可以統一由環境類Context來實作狀态的轉換。此時,增加新的具體狀态類可能需要修改其他具體狀态類或者環境類的源代碼,否則系統無法轉換到新增狀态。但是對于用戶端來說,無須關心狀态類,可以為環境類設定預設的狀态類,而将狀态的轉換工作交給具體狀态類或環境類來完成,具體的轉換細節對于用戶端而言是透明的。
在上面的“銀行賬戶狀态轉換”執行個體中,我們通過具體狀态類來實作狀态的轉換,在每一個具體狀态類中都包含一個stateCheck()方法,在該方法内部實作狀态的轉換,除此之外,我們還可以通過環境類來實作狀态轉換,環境類作為一個狀态管理器,統一實作各種狀态之間的轉換操作。
下面通過一個包含循環狀态的簡單執行個體來說明如何使用環境類實作狀态轉換:
Sunny軟體公司某開發人員欲開發一個螢幕放大鏡工具,其具體功能描述如下: 使用者單擊“放大鏡”按鈕之後螢幕将放大一倍,再點選一次“放大鏡”按鈕螢幕再放大一倍,第三次點選該按鈕後螢幕将還原到預設大小。 |
可以考慮使用狀态模式來設計該螢幕放大鏡工具,我們定義三個螢幕狀态類NormalState、LargerState和LargestState來對應螢幕的三種狀态,分别是正常狀态、二倍放大狀态和四倍放大狀态,螢幕類Screen充當環境類,其結構如圖6所示:
圖6 螢幕放大鏡工具結構圖
本執行個體核心代碼如下所示:
//螢幕類
class Screen {
//枚舉所有的狀态,currentState表示目前狀态
private State currentState, normalState, largerState, largestState;
public Screen() {
this.normalState = new NormalState(); //建立正常狀态對象
this.largerState = new LargerState(); //建立二倍放大狀态對象
this.largestState = new LargestState(); //建立四倍放大狀态對象
this.currentState = normalState; //設定初始狀态
this.currentState.display();
}
public void setState(State state) {
this.currentState = state;
}
//單擊事件處理方法,封轉了對狀态類中業務方法的調用和狀态的轉換
public void onClick() {
if (this.currentState == normalState) {
this.setState(largerState);
this.currentState.display();
}
else if (this.currentState == largerState) {
this.setState(largestState);
this.currentState.display();
}
else if (this.currentState == largestState) {
this.setState(normalState);
this.currentState.display();
}
}
}
//抽象狀态類
abstract class State {
public abstract void display();
}
//正常狀态類
class NormalState extends State{
public void display() {
System.out.println("正常大小!");
}
}
//二倍狀态類
class LargerState extends State{
public void display() {
System.out.println("二倍大小!");
}
}
//四倍狀态類
class LargestState extends State{
public void display() {
System.out.println("四倍大小!");
}
}
在上述代碼中,所有的狀态轉換操作都由環境類Screen來實作,此時,環境類充當了狀态管理器角色。如果需要增加新的狀态,例如“八倍狀态類”,需要修改環境類,這在一定程度上違背了“開閉原則”,但對其他狀态類沒有任何影響。
編寫如下用戶端代碼進行測試:
class Client {
public static void main(String args[]) {
Screen screen = new Screen();
screen.onClick();
screen.onClick();
screen.onClick();
}
}
輸出結果如下:
正常大小! 二倍大小! 四倍大小! 正常大小! |
【作者:劉偉 http://blog.csdn.net/lovelion】