设计模式之状态模式

设计模式之状态模式

状态模式简介

有时候,会遇到这样的情形,某一个对象,有多种不同的状态,在不同的状态下,可能有不同的行为。要实现这样一种服务,可以使用最简单的if.else结构,但是呢,这种方式在状态比较多的时候就会使得代码变得比较冗长,每次有新的状态的时候,都需要修改该处代码,而且,在后期进行维护的时候,也不便于理解;还有另一一种方式,就是状态模式,所谓的状态模式,通俗地来讲,就是把对象的所有状态进行封装,将每一个状态独立抽取出来,形成一个状态类,这样,当需要增加新的状态的时候,就不需要更改原有的代码了。

状态模式的具体实现

这里来简单模拟一个号码卡的三种状态(正常状态,欠费状态,停机状态)变化来更加深入的了解状态模式。

当余额大于0的时候处于正常状态,当余额小于0但是大于-50的时候,处于欠费状态,此时依旧可以打电话,当欠费超过50的时候,处于停止状态,此时打电话功能将被限制

首先是没有使用状态模式的情景,也就是通过冗长的if.else语句结构来实现这样一个过程


/**
 * Created by Huanfeng.Xu on 2017-06-26.
 */
public class Original {

    public Original(double money){
        this.money = money;
        state = NORMAL;
    }

    private double money;
    private String state;

    private final static String STOP = "stop";
    private final static String NORMAL = "normal";
    private final static String OWNED = "owned";

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }
    // 调用具体的业务方法的时候任然需要进行状态的校验,根据不同的状态采取不同的行为
    public void call(){
        check();
        if (STOP.equals(state)){
            System.out.println("当前账号处于停机状态,不允许打电话也不允许接听电话");
        }else{
            if (OWNED.equals(state)){
                System.out.println("当前账号处于欠费状态,请注意, 欠费金额 " +  money);
            }else if (NORMAL.equals(state)){
                System.out.println("打电话中...");
            }
            money -= 10;
        }
    }
    // 查看当前系统的状态
    public void check(){
        if (money < -50){
            state = STOP;
        }else if (money < 0 && money >= -50){
            state = OWNED;
        }else if (money >= 0){
            state = NORMAL;
        }
    }

    public void charge(double money){
        this.money += money;
        System.out.println("充值费用 " + money);
        check();
    }
}

从上面的代码中可以看到,每次执行一个业务方法的时候,都需要检查此时系统所处的状态,然后再根据不同的业务方法,判断不同状态下应该有的行为,当业务方法比较多的时候,整个的代码就会变得相对冗余了,而且修改起来几乎每一个业务方法都需要进行修改

接下来来看下使用状态模式之后的情况


/**
 * Created by Huanfeng.Xu on 2017-06-26.
 */
public class Account {
    private double money;
    private State state;

   // 省略set/get方法

    public void call(){
        state.call();
    }

    public void charge(double money){
        state.charge(money);
    }
}

// 抽象的状态类
abstract class State{
    protected Account account;

    public abstract void checkState();
    public  void charge(double money){
        account.setMoney(account.getMoney() + money);
        System.out.println("充值费用 " + money);
        checkState();
    }
    public abstract void call();
}

//正常状态类
class Normal extends State{

    public Normal(Account account){
        this.account = account;
    }

    @Override
    public void checkState() {
        double currentMoney = account.getMoney();
        if (currentMoney < 0 && currentMoney >= -50 ){
            System.out.println("当前账号余额不足,已经处于欠费状态,欠费 " + account.getMoney());
            account.setState(new Owned(account));
        }else if (currentMoney < -50){
            System.out.println("欠费过多,账号已经停机");
            account.setState(new Stopped(account));
        }
    }

    @Override
    public void call() {
        account.setMoney(account.getMoney() - 10);
        System.out.println("打电话中...");
        checkState();
    }
}
//欠费状态类
class Owned extends State{

    public Owned(Account account){
        this.account = account;
    }

    @Override
    public void checkState() {
        double currentMoney = account.getMoney();
        if (currentMoney > 0){
            account.setState(new Normal(account));
        }else if (currentMoney < -50){
            account.setState(new Stopped(account));
        }
    }

    @Override
    public void call() {
        System.out.println("当前账号处于欠费状态,请注意, 欠费金额 " + account.getMoney());
        account.setMoney(account.getMoney() - 10);
        checkState();
    }
}
// 停机状态类
class Stopped extends State{

    public Stopped(Account account){
        this.account = account;
    }
    @Override
    public void checkState() {
        double currentMoney = account.getMoney();
        if (currentMoney > 0){
            System.out.println("账号已经恢复正常");
            account.setState(new Normal(account));
        }
    }

    @Override
    public void call() {
        System.out.println("当前账号处于停机状态,不允许打电话也不允许接听电话");
    }
}

可以看到,此时将状态的变化交给了状态类本身,不用的状态类根据当前的行为,操作之后自动切换到不同的状态,此时就不再需要进行状态的检测了,账号类(环境类)所拥有的状态就是当前的状态了。并且把不同的状态的行为封装起来,此时,不同的状态类只需要负责自己的行为判断即可。当需要修改的时候,所需要修改的也仅仅是对应的状态类的行为了,而再是对每一个的业务方法都进行修改。

总结

状态模式,主要的思想就是把不同的状态及其行为抽取出来,封装成对应的状态对象,可以理解是将原本比较庞大的if.else语句抽取出来,分散到各自对应的状态之中,使得之后的修改都是直接针对对象进行修改,增加代码的可维护性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值