设计模式之状态模式
来源:互联网 发布:标签权重算法 编辑:程序博客网 时间: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语句抽取出来,分散到各自对应的状态之中,使得之后的修改都是直接针对对象进行修改,增加代码的可维护性。
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之--状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 设计模式之状态模式
- 【设计模式】之状态模式
- 《数据库技术原理与应用教程》一第一篇 基础篇
- JS辨别访问浏览器判断是android还是ios系统
- Spring Boot应用的后台运行配置
- Consul注销实例时候的问题
- 新年彩蛋:Spring Boot自定义Banner
- 设计模式之状态模式
- 使用Intellij中的Spring Initializr来快速构建Spring Boot/Cloud工程
- 在传统Spring应用中使用spring-boot-actuator模块提供监控端点
- 我的新书《Spring Cloud微服务实战》预告
- 24 shell变量(自定义变量、环境变量、位置参数变量、预定义变量)
- SpringCloud实战小贴士:版本依赖关系
- git 克隆远程仓库
- 使用Spring Boot Actuator、Jolokia和Grafana实现准实时监控
- Android如何解决Gradle编译慢