狀態(tài)模式允許一個對象的內(nèi)部狀態(tài)改變的時候改變其行為
缺點是會造出大量的狀態(tài)類肩榕,優(yōu)點是使程序免于大量的條件轉(zhuǎn)移語句
- 什么時候可以用?
- 對象的行為隨著狀態(tài)的改變而改變
- 對象的某一個方法里依賴于一重或多重的條件轉(zhuǎn)移語句
狀態(tài)模式和策略模式的區(qū)別:
考察環(huán)境角色是否有明顯的狀態(tài)和狀態(tài)的轉(zhuǎn)變蓄髓,有就用狀態(tài)模式缤弦,否則用策略模式,通過一個Context環(huán)境角色晰韵,使得各個原本一個環(huán)境只用一個策略類的可以用很多個了。
上類圖:
狀態(tài)模式.png
例子:
-
TCP
image.png -
繪圖軟件
image.png 代碼示例:
模擬購物的幾個動作,選擇商品鹏倘,生成訂單,付款取貨
- 先定義個接口
package com.byedbl.state;
/**
* A state interface
* 用戶在網(wǎng)上購物的狀態(tài)變化:
* 選擇商品 --> 生成訂單 --> 付款取貨
*/
public interface ShopState {
void execute();
void changeState(ShopContext c, AbstractShopState shopState);
}
changeState
是為了內(nèi)部修改狀態(tài)方便的一個方法肺稀,允許子類自行決定下一個狀態(tài)是哪個第股,增加靈活性,當然也可以去掉话原,下面這個抽象類專門處理該方法夕吻。
- 抽象類處理
changeState
package com.byedbl.state;
/**
* The parent class of state
*/
public abstract class AbstractShopState implements ShopState {
public AbstractShopState() {
}
@Override
public void changeState(ShopContext c, AbstractShopState s) {
c.changeState(s);
}
}
- 實現(xiàn)3個狀態(tài)的邏輯
購物shop
package com.byedbl.state;
/**
* A concrete state for customer shopping
*/
public class Shop extends AbstractShopState {
private static Shop shop;
private Shop() {
}
static {
shop = new Shop();
}
public static Shop getInstance() {
return shop;
}
@Override
public void execute() {
System.out.println("The state is shopping now !");
}
}
生成訂單
package com.byedbl.state;
/**
* A concrete state for generating bill
*/
public class GenerateBill extends AbstractShopState {
private static GenerateBill generateBill;
static {
generateBill = new GenerateBill();
}
private GenerateBill() {
}
public static GenerateBill getInstance() {
return generateBill;
}
@Override
public void execute() {
System.out.println("The state is generating bill now !");
}
}
付款
package com.byedbl.state;
/**
* A concrete state for customer shopping
*/
public class Pay extends AbstractShopState {
private static Pay pay ;
static {
pay = new Pay();
}
private Pay() {
}
public static Pay getInstance() {
return pay;
}
@Override
public void execute() {
System.out.println("The state is pay now !");
}
}
- 環(huán)境角色類
package com.byedbl.state;
/**
* The context for user useing
*/
public class ShopContext {
private ShopState currentState;
public ShopContext() {
}
public void changeState(ShopState s) {
currentState = s;
}
public void shop() {
currentState.execute();
}
public void generateBill() {
currentState.execute();
}
public void pay() {
currentState.execute();
}
}
- 客戶端用法
package com.byedbl.state;
/**
* A test client
*/
public class Test {
public static void main(String[] args) {
ShopContext myContext = new ShopContext();
AbstractShopState myShop = Shop.getInstance();
AbstractShopState myGenBill = GenerateBill.getInstance();
AbstractShopState myPay = Pay.getInstance();
myContext.changeState(myShop);
myContext.shop();
myContext.changeState(myGenBill);
myContext.generateBill();
myContext.changeState(myPay);
myContext.pay();
myShop.changeState(myContext, myPay);
myContext.pay();
}
}
狀態(tài)模式關(guān)鍵是一個環(huán)境角色,這個角色使得可以各個狀態(tài)可以自由切換繁仁。