用State模式减少if..elseif语句

2024-02-16 23:32

本文主要是介绍用State模式减少if..elseif语句,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

这种方式可以适用于很多场合,就像现在做的学习平台项目,也可以用在上面去。资源有视频、ppt等等类型,当不同类型的时候就调用不同的方法。就可以把它做成个便于维护和通用的。

注重这种模式的理解!!!

我们在写程序的过程中会遇到很多的逻辑判断,一般都是用if ..else、if..else if、swith(..) case等来做判断,然后根据结果做一下分支处理,这样写虽然方便,但会增加以后的维护难度,假如有上百个if ..else if判断,估计后期维护的人看到代码头都大了。像这种情况可以用state模式来解决。

  State模式是行为模式之一。当某个对象的内部状态(通俗的说,成员变量)发生改变,它的行为也会发生改变。

  状态模式的角色:
抽象状态、具体状态(一种或多个状态,每种状态对应不同的行力),环境(context)角色(就是对象,包括当前对象状态、改变状态的方法和状态行为方法)

  为了帮助理解,举例说明:

  一个画图程序,有一个控制面板,上面罗列了各种画图工具以及其它颜色选择,滴管等工具,当用户选择或改变了画图工具时,就可以使用各种不同的工具进行画图或其他操作了。
我们把这个过程用另外一种方法再描述一下:
- 用户选择画图工具就是一个画笔状态的改变。
- 每个工具能画的图形可能完全不一样,也就是说它们的行为各不一样。
- 改变了画图工具,在画布上画出的图形当然也不一样了,换句话说,画笔状态的改变导致行为的不一样。
 再举个例子,100米短跑远动员。他有三种状态,生病状态,正常状态,兴奋状态。那么状态决定这个运动员的行为,生病状态跑的速度慢,兴奋状态跑的速度快。我们以运动员程序为例,如果不用设计模式的话,我们可能会这写


package com.bill99.pattern;/***<p>title: 一般运动员</p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class Gamer {private final int NORMAL_STATE = 0; //正常状态private final int MALUM_STATE =1;   //生病状态private final int EXCITED_STATE =2; //兴奋状态private int state = 0;public void setState(int state){this.state = state;}public void run() {if(state == NORMAL_STATE) {       //正常状态下跑System.out.println("100米,跑完共用时15秒!");} else if(state == MALUM_STATE) { //生病状态下跑System.out.println("100米,跑完共用时20秒!");} else if(state == EXCITED_STATE) {//兴奋状态下跑System.out.println("100米,跑完共用时10秒!");} else {System.out.println("未知的状态");}}
}

如果以后维护的话,要再加一个超级兴奋的状态,得要改原来的源代码,添加一个代表超级兴奋的成员变量,再改if..else if判断,这样做不符合OO设计原则,实现不了程序的松耦合。

下面用状态模式来实现

package com.bill99.pattern.state;/***<p>title:状态接口 </p>*<p>Description:状态接口,每一个状态都要实现此接口 </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public interface IState {/*** 起跑*/public void doRun();
}

package com.bill99.pattern.state;/***<p>title: 兴奋状态运动员</p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class ExcitedState implements IState {public void doRun() {System.out.println("100米,跑完共用时10钞!");}
}

package com.bill99.pattern.state;/***<p>title:生病状态运动员 </p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class MalumState implements IState {public void doRun() {System.out.println("100米,跑完共用时20秒!");}
}

package com.bill99.pattern.state;/***<p>title:正常状态运动员 </p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class NormalState implements IState {public void doRun() {System.out.println("100米,跑完共用时15秒!");}
}

构建一个场景,运动员类,该运动员类包括表示当前对象状态的成员变量,改变当前状态的方法,和状态行为方法


package com.bill99.pattern.state;/***<p>title: 采用状态模式的运动员</p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class Gamer {//当前状态private IState state = new NormalState();//改变状态的方法public void setState(IState state){this.state = state;}//状态行为方法,同上面的Gamer 类相比这里没有if..else if判断public void run() {state.doRun();}
}

测试类
package com.bill99.pattern.state;/***<p>title: 测试类</p>*<p>Description: </p>*<p>CopyRight: CopyRight (c) 2009</p>*<p>Company: 99bill.com</p>*<p>Create date: 2009-11-3</P>*@author Zhang Weiyang <sunnylocus@163.com>*/
public class StateTest {public static void main(String[] args) {//没有使用状态设计模式com.bill99.pattern.Gamer game = new com.bill99.pattern.Gamer();game.setState(0);game.run();game.setState(1);game.run();game.setState(2);game.run();System.out.println("---------------------");//使用状态设计模式//正常状态下跑 Gamer gamer = new Gamer();gamer.run(); //生病状态下跑gamer.setState(new MalumState());gamer.run();//兴奋状态下跑gamer.setState(new ExcitedState());gamer.run();}
}

运行结果:

100米,跑完共用时15秒!
100米,跑完共用时20秒!
100米,跑完共用时10秒!
———————
100米,跑完共用时15秒!
100米,跑完共用时20秒!
100米,跑完共用时10钞!

 

假如我们再扩展一个超级兴奋的状态SuperExcitedState,只需实现IState接口,定义好该状态的行为,调用如下

gamer.setState(new  SuperExcitedState());

gamer.run();

而不用改原有代码,提高程序的松耦合。

原文链接: http://sunnylocus.iteye.com/blog/509423

这篇关于用State模式减少if..elseif语句的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/716012

相关文章

Java设计模式---迭代器模式(Iterator)解读

《Java设计模式---迭代器模式(Iterator)解读》:本文主要介绍Java设计模式---迭代器模式(Iterator),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,... 目录1、迭代器(Iterator)1.1、结构1.2、常用方法1.3、本质1、解耦集合与遍历逻辑2、统一

Java 线程安全与 volatile与单例模式问题及解决方案

《Java线程安全与volatile与单例模式问题及解决方案》文章主要讲解线程安全问题的五个成因(调度随机、变量修改、非原子操作、内存可见性、指令重排序)及解决方案,强调使用volatile关键字... 目录什么是线程安全线程安全问题的产生与解决方案线程的调度是随机的多个线程对同一个变量进行修改线程的修改操

Mysql常见的SQL语句格式及实用技巧

《Mysql常见的SQL语句格式及实用技巧》本文系统梳理MySQL常见SQL语句格式,涵盖数据库与表的创建、删除、修改、查询操作,以及记录增删改查和多表关联等高级查询,同时提供索引优化、事务处理、临时... 目录一、常用语法汇总二、示例1.数据库操作2.表操作3.记录操作 4.高级查询三、实用技巧一、常用语

XML重复查询一条Sql语句的解决方法

《XML重复查询一条Sql语句的解决方法》文章分析了XML重复查询与日志失效问题,指出因DTO缺少@Data注解导致日志无法格式化、空指针风险及参数穿透,进而引发性能灾难,解决方案为在Controll... 目录一、核心问题:从SQL重复执行到日志失效二、根因剖析:DTO断裂引发的级联故障三、解决方案:修复

SQL BETWEEN 语句的基本用法详解

《SQLBETWEEN语句的基本用法详解》SQLBETWEEN语句是一个用于在SQL查询中指定查询条件的重要工具,它允许用户指定一个范围,用于筛选符合特定条件的记录,本文将详细介绍BETWEEN语... 目录概述BETWEEN 语句的基本用法BETWEEN 语句的示例示例 1:查询年龄在 20 到 30 岁

C++高效内存池实现减少动态分配开销的解决方案

《C++高效内存池实现减少动态分配开销的解决方案》C++动态内存分配存在系统调用开销、碎片化和锁竞争等性能问题,内存池通过预分配、分块管理和缓存复用解决这些问题,下面就来了解一下... 目录一、C++内存分配的性能挑战二、内存池技术的核心原理三、主流内存池实现:TCMalloc与Jemalloc1. TCM

Redis Cluster模式配置

《RedisCluster模式配置》:本文主要介绍RedisCluster模式配置,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录分片 一、分片的本质与核心价值二、分片实现方案对比 ‌三、分片算法详解1. ‌范围分片(顺序分片)‌2. ‌哈希分片3. ‌虚

RabbitMQ工作模式中的RPC通信模式详解

《RabbitMQ工作模式中的RPC通信模式详解》在RabbitMQ中,RPC模式通过消息队列实现远程调用功能,这篇文章给大家介绍RabbitMQ工作模式之RPC通信模式,感兴趣的朋友一起看看吧... 目录RPC通信模式概述工作流程代码案例引入依赖常量类编写客户端代码编写服务端代码RPC通信模式概述在R

Mybatis Plus JSqlParser解析sql语句及JSqlParser安装步骤

《MybatisPlusJSqlParser解析sql语句及JSqlParser安装步骤》JSqlParser是一个用于解析SQL语句的Java库,它可以将SQL语句解析为一个Java对象树,允许... 目录【一】jsqlParser 是什么【二】JSqlParser 的安装步骤【三】使用场景【1】sql语

sql语句字段截取方法

《sql语句字段截取方法》在MySQL中,使用SUBSTRING函数可以实现字段截取,下面给大家分享sql语句字段截取方法,感兴趣的朋友一起看看吧... 目录sql语句字段截取sql 截取表中指定字段sql语句字段截取1、在mysql中,使用SUBSTRING函数可以实现字段截取。例如,要截取一个字符串字