状态模式允许一个对象的内部状态改变的时候改变其行为
缺点是会造出大量的状态类,优点是使程序免于大量的条件转移语句
- 什么时候可以用?
- 对象的行为随着状态的改变而改变
- 对象的某一个方法里依赖于一重或多重的条件转移语句
状态模式和策略模式的区别:
考察环境角色是否有明显的状态和状态的转变,有就用状态模式,否则用策略模式,通过一个Context环境角色,使得各个原本一个环境只用一个策略类的可以用很多个了。
上类图:
例子:
-
TCP
-
绘图软件
代码示例:
模拟购物的几个动作,选择商品,生成订单,付款取货
- 先定义个接口
package com.byedbl.state;
/**
* A state interface
* 用户在网上购物的状态变化:
* 选择商品 --> 生成订单 --> 付款取货
*/
public interface ShopState {
void execute();
void changeState(ShopContext c, AbstractShopState shopState);
}
changeState
是为了内部修改状态方便的一个方法,允许子类自行决定下一个状态是哪个,增加灵活性,当然也可以去掉,下面这个抽象类专门处理该方法。
- 抽象类处理
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);
}
}
- 实现3个状态的逻辑
购物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 !");
}
}
- 环境角色类
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();
}
}
状态模式关键是一个环境角色,这个角色使得可以各个状态可以自由切换。