【1】基本概念
狀態模式(State),當一個對象的內在狀態改變時允許改變其行為,這個對象看起來像是改變了其類。
【2】簡單分析
我們先來看下該設計模式的UML的結構圖
【3】如何用Java語言實現該設計模式
本篇文章以一個貼近現實生活的例子來展示如何使用該設計模式,以方便大家儘快的掌握狀態設計模式。例子:如某人去銀行新開一個賬戶,該賬戶可以用來存錢或者取錢,我們可以以賬戶中的總資金來判斷顯示某使用者賬戶的狀態:紅色狀態(RedState),銀色狀態(SliverState),金色狀態GoldState)。其實就好比銀行中根據我們儲存卡中的資金來給客戶某種身份的識別,例如普通使用者,VIP客戶,公司客戶....等等。
我們先看下該執行個體Demo的結構圖:
3.1 State.java 源碼:
package com.andyidea.patterns.concretestate;import com.andyidea.patterns.context.Account;/** * State類,抽象狀態類,定義一個介面以封裝 * 與Context的一個特定狀態相關的行為。 * @author Andy * */public abstract class State { protected Account account; protected double balance; protected double interest; protected double lowerLimit; protected double upperLimit; //-------------Properties------------------// public Account getAccount() {return account;}public void setAccount(Account account) {this.account = account;}public double getBalance() {return balance;}public void setBalance(double balance) {this.balance = balance;}//------------------------------------------///**存入金額*/public abstract void deposit(double amount);/**支出金額*/ public abstract void withdraw(double amount); /**利息*/ public abstract void payInterest();}
3.2 RedState.java源碼:
package com.andyidea.patterns.concretestate;/** * 使用者賬戶狀態:RedState * @author Andy * ConcreteState類,具體狀態,每一個子類實現一個與 * Context的一個狀態相關的行為。 */public class RedState extends State {private double serviceFee;public RedState(State state) {this.balance = state.getBalance();this.account = state.getAccount();initialize();} /** 類比初始化基礎資料*/private void initialize() {interest = 0.0;lowerLimit = -100.0;upperLimit = 0.0;serviceFee = 15.00;}@Overridepublic void deposit(double amount) { balance += amount; stateChangeCheck();}@Overridepublic void withdraw(double amount) { amount = amount - serviceFee; System.out.println("No funds available for withdrawal!");}@Overridepublic void payInterest() {// No interest is paid}/** 狀態檢測 */private void stateChangeCheck() {if (balance > upperLimit) {account.setState(new SilverState(this));}}}
SliverState.java源碼:
package com.andyidea.patterns.concretestate;import com.andyidea.patterns.context.Account;/** * 使用者賬戶狀態:SilverState * @author Andy * ConcreteState類,具體狀態,每一個子類實現一個與 * Context的一個狀態相關的行為。 */public class SilverState extends State { public SilverState(State state){ this(state.balance,state.account); } public SilverState(double balance, Account account){ this.balance = balance; this.account = account; initialize(); } /** 類比初始化基礎資料*/ private void initialize(){ interest = 0.0; lowerLimit = 0.0; upperLimit = 1000.0; }@Overridepublic void deposit(double amount) { balance += amount; stateChangeCheck();}@Overridepublic void withdraw(double amount) { balance -= amount; stateChangeCheck();}@Overridepublic void payInterest() { balance += interest * balance; stateChangeCheck();}/** 狀態檢測 */ private void stateChangeCheck(){ if (balance < lowerLimit){ account.setState(new RedState(this)); } else if (balance > upperLimit){ account.setState(new GoldState(this)); } }}
GoldState.java源碼:
package com.andyidea.patterns.concretestate;import com.andyidea.patterns.context.Account;/** * 使用者賬戶狀態:GoldState * @author Andy * ConcreteState類,具體狀態,每一個子類實現一個與 * Context的一個狀態相關的行為。 */public class GoldState extends State { public GoldState(State state){ this(state.balance, state.account); } public GoldState(double balance, Account account){ this.balance = balance; this.account = account; initialize(); } /** 類比初始化基礎資料*/ private void initialize(){ interest = 0.05; lowerLimit = 1000.0; upperLimit = 10000000.0; }@Overridepublic void deposit(double amount) { balance += amount; stateChangeCheck();}@Overridepublic void withdraw(double amount) { balance -= amount; stateChangeCheck();}@Overridepublic void payInterest() { balance += interest * balance; stateChangeCheck();}/** 狀態檢測 */private void stateChangeCheck() {if (balance < 0.0) {account.setState(new RedState(this));} else if (balance < lowerLimit) {account.setState(new SilverState(this));}}}
3.3 Account.java類源碼:
package com.andyidea.patterns.context;import com.andyidea.patterns.concretestate.SilverState;import com.andyidea.patterns.concretestate.State;/** * Context類,維護一個ConcreteState子類的執行個體 * 這個執行個體定義當前的狀態。 * @author Andy * */public class Account { private State state; private String owner; public Account(String owner){ // 新開賬戶預設為 Silver狀態 this.owner = owner; this.state = new SilverState(0.0, this); } public State getState() {return state;}public void setState(State state) {this.state = state;}public void deposit(double amount) {state.deposit(amount);System.out.println(owner + " Deposited " + amount);System.out.println(owner + " Balance = " + state.getBalance());System.out.println("Status = " + state.getClass().getSimpleName());System.out.println("==============================================");} public void withdraw(double amount){ state.withdraw(amount); System.out.println(owner + " Withdrew " + amount); System.out.println(owner + " Balance = " + state.getBalance()); System.out.println("Status = " + state.getClass().getSimpleName()); System.out.println("=============================================="); } public void payInterest(){ state.payInterest(); System.out.println(owner + " Interest Paid "); System.out.println(owner + " Balance = " + state.getBalance()); System.out.println("Status = " + state.getClass().getSimpleName()); System.out.println("=============================================="); }}
3.4 用戶端測試類別 StateClient.java 類源碼:
package com.andyidea.patterns;import com.andyidea.patterns.context.Account;public class StateClient {public static void main(String[] args) { // 新開一個銀行賬戶 Account account = new Account("Andy.Chen"); // 存取款等系列操作 account.deposit(500.0); account.deposit(300.0); account.deposit(550.0); account.payInterest(); account.withdraw(2000.00); account.withdraw(1100.00);}}
【4】下面我們來看下程式啟動並執行結果:
Andy.Chen Deposited 500.0Andy.Chen Balance = 500.0Status = SilverState==============================================Andy.Chen Deposited 300.0Andy.Chen Balance = 800.0Status = SilverState==============================================Andy.Chen Deposited 550.0Andy.Chen Balance = 1350.0Status = GoldState==============================================Andy.Chen Interest Paid Andy.Chen Balance = 1417.5Status = GoldState==============================================Andy.Chen Withdrew 2000.0Andy.Chen Balance = -582.5Status = RedState==============================================No funds available for withdrawal!Andy.Chen Withdrew 1100.0Andy.Chen Balance = -582.5Status = RedState==============================================
【5】總結:
狀態模式主要解決的是當控制一個對象狀態轉換的條件運算式過於複雜時的情況。把狀態的判斷邏輯轉移到表示不同狀態的一系列類當中,可以把複雜的判斷邏輯簡化。當一個對象的行為取決於它的狀態,並且它必須在運行時刻根據狀態改變它的行為時,就可以考慮使用狀態模式了。
本文為 Andy.Chen 原創,歡迎大家繼續關注Me的博文,歡迎大家轉載,謝謝!