设计模式之状态模式

来源:互联网 发布:标签权重算法 编辑:程序博客网 时间:2024/05/16 18:39

设计模式之状态模式

状态模式简介

有时候,会遇到这样的情形,某一个对象,有多种不同的状态,在不同的状态下,可能有不同的行为。要实现这样一种服务,可以使用最简单的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语句抽取出来,分散到各自对应的状态之中,使得之后的修改都是直接针对对象进行修改,增加代码的可维护性。

原创粉丝点击