1.为什么要使用状态模式?
思考这样一个场景:当一个对象的动作和其所处的状态相关时,比如我要给某用户发送优惠券,当用户状态正常时,我才可以发,当用户状态是冻结的时候,我就不能给他发送(发了他也用不了)。由此我们可以用一下的代码来实现。
public void sendCoupon(Account account){
if(account.state == "normal"){
//发
}
if(account.state == "freeze"){
//不发
}
if(account.state == 'XXXXXX'){
//不发
}
}
这段代码非常简单,这个场景也十分简单。现在我们假设用户有10几种状态(正常、冻结、禁用...等),只有在正常状态下才可以发送优惠券,那么我们要这样一直if下去吗?有人说可以if一个其它用else,不错,但是如果我们的方法要求不同状态下返回不同的结果,那就不能if else 了,必须根据情况一个个判断。由此,我们可以使用状态模式来简化代码了。
2.先看一波类图
这个类图还是比较好玩的,看Context和State,他们互相包含了对方。
3.实现
state相关类
public abstract class State {
private Context context;
public Context getContext() {
return context;
}
public void setContext(Context context) {
this.context = context;
}
//定义方法
public abstract void sendCoupon();
}
public class NormalState extends State{
@Override
public void sendCoupon() {
System.out.println("用户状态正常,发送");
}
}
public class FreezeState extends State{
@Override
public void sendCoupon() {
System.out.println("用户状态冻结,不发送优惠券");
//假设给它恢复到正常状态
super.getContext().setState(new NormalState());
System.out.println("用户状态恢复正常");
super.getContext().sendCoupon();
}
}
Context相关类
public class Context {
private State state;
public State getState() {
return state;
}
public void setState(State state) {
this.state = state;
}
//利用一个封装
public void sendCoupon(){
this.state.sendCoupon();
}
}
main方法
public class Main {
public static void main(String[] args) {
Context context = new Context();
context.setState(new NormalState());
context.sendCoupon();
System.out.println("=============");
FreezeState state = new FreezeState();
state.setContext(context);
context.setState(state);
context.sendCoupon();
}
}
//输出结果
用户状态正常,发送
=============
用户状态冻结,不发送优惠券
用户状态恢复正常
用户状态正常,发送
4.总结
状态模式适用与当一个对象的行为和他的状态相关时。当