1、概念
应用场景:一个对像处于不同的状态,调用相同的方法时产生不同的行为。
目的:将对象本身的表示与对象状态的变迁逻辑解耦。
角色:状态角色、上下文角色。状态代表上下文所处的状态,上下文为状态中方法的实现提供支持。
实现方法:为状态定义抽象类,其中包含对上下文对象的引用,以便调用上下文的方法。包含负责改变、迁移状态的方法。
上下文类的实现包含一个状态实例,上下文中的方法在实现时要调用状态的方法。
2、实现示例
状态模式在现实中经常碰到。假如一个API发布系统,所有API在新创建时都处于只可以浏览的状态,不可以执行其中的方法,执行也无效。用户只有在对API下了定单以后,才可以执行其中的方法。对于已经下过定单的API,还可以取消下单。最终的目的,API处于不同的状态,那么它的方法行为是不同的。代码如下:
package com.zhangxf.state;
// 代表状态的抽象类
abstract class State {
private String stateName;
protected MyApi api;
public State(String stateName, MyApi api) {
this.stateName = stateName;
this.api = api;
}
public String getStateName() {
return stateName;
}
public void setStateName(String stateName) {
this.stateName = stateName;
}
public MyApi getMyApi() {
return api;
}
public void setMyApi(MyApi api) {
this.api = api;
}
public void display() {
System.out.println("API Name: " + api.getApiName());
System.out.println("API State: " + stateName);
}
// 下单
abstract public boolean order();
// 调用
abstract public boolean invoke();
// 取消下单
abstract public boolean unOrder();
}
// 可浏览状态
class BrowserState extends State {
public BrowserState(MyApi api) {
super("Browser", api);
}
// 由可浏览状态变成可调用状态
@Override
public boolean order() {
System.out.println("Order " + api.getApiName() + ": OK");
api.setState(new InvokeState(api));
return true;
}
// 不可以调用,必需先下单
@Override
public boolean invoke() {
System.out.println("Can not invoke " + api.getApiName() + ": Order first");
return false;
}
// 不可以取消下单,必需先下单
@Override
public boolean unOrder() {
System.out.println("Can not unorder " + api.getApiName() + ": Order first");
return false;
}
}
// 可调用状态
class InvokeState extends State {
public InvokeState(MyApi api) {
super("Invoke", api);
}
// 重复下单
@Override
public boolean order() {
System.out.println("Order " + api.getApiName() + ": Order repeat");
return true;
}
// 可以调用
@Override
public boolean invoke() {
System.out.println("Invoke " + api.getApiName() + ": OK");
return true;
}
// 可以取消下单,恢复到浏览状态
@Override
public boolean unOrder() {
System.out.println("unOrder " + api.getApiName() + ": OK");
api.setState(new BrowserState(api));
return true;
}
}
class MyApi {
public MyApi(String apiName) {
this.apiName = apiName;
state = new BrowserState(this);
}
private String apiName;
private State state;
public void setapiName(String apiName) {
this.apiName = apiName;
}
public String getApiName() {
return apiName;
}
public void setState(State state) {
this.state = state;
}
public State getState() {
return state;
}
public boolean order() {
return state.order();
}
public boolean invoke() {
return state.invoke();
}
public boolean unOrder() {
return state.unOrder();
}
}
public class StatePattern {
public static void main(String[] args) {
// 新创建API,此时牌浏览状态
MyApi api = new MyApi("MyApi");
// 还没有下单,返回false
api.invoke();
// 还没有下单,返回false
api.unOrder();
// 下单,API状态由浏览状态变成可调用状态
api.order();
// 已经是可调用状态,这个是重复下单
api.order();
// 可以调用
api.invoke();
// 可以取消下单
api.unOrder();
}
}
运行结果:
Can not invoke MyApi: Order first
Can not unorder MyApi: Order first
Order MyApi: OK
Order MyApi: Order repeat
Invoke MyApi: OK
unOrder MyApi: OK
3、策略模式
为对象提供不同的策略实现,对象的方法就有不同的行为。策略模式的概念、实现方式与状态模式一模一样,策略就是状态。并且实现起来比状态模式要简单一些。在上例中order方法与unOrder方法负责状态的变化、迁移。而策略模式不用,只需要提供一个方法供用户修改具体的策略就可,具体是什么策略由使用者决定。