`
sunnylocus
  • 浏览: 869662 次
  • 性别: Icon_minigender_1
  • 来自: 美国图森
社区版块
存档分类
最新评论

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

    博客分类:
  • Java
阅读更多

   我们在写程序的过程中会遇到很多的逻辑判断,一般都是用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();

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

5
0
分享到:
评论
8 楼 liuzhiwenac 2014-10-29  
各位童鞋,这个最大的好处是实现了“对修改关闭,对扩展开放”,无疑代码会更好维护,更健壮。
7 楼 huangheyuan1229 2013-07-11  
z这个是strategy模式
6 楼 zuishengmengsi1990 2012-05-02  
[b][/b][i][/i][u][/u]
引用
[img][/img][flash=200,200][/flash]

    [*]

    [*]

    [*]

    [*]

    [*]

    [*]

    [*]

    [*]

    [*]

    [*]
[color=darkred][/color][/u][u]
5 楼 k1280000 2011-10-14  
sopships 写道
javne 写道
但是类多了

同感,除非业务内容很多的情况下用,不过好像比较少吧
不过思路可以学习学习


匿名类 ?
4 楼 k1280000 2011-10-14  
匿名类呢 ?
3 楼 gstripe 2010-04-20  
类多了其实也没什么 不要的类删了就是, 重要的是 只要添加类 而不用去该原有的代码。
2 楼 sopships 2010-04-08  
javne 写道
但是类多了

同感,除非业务内容很多的情况下用,不过好像比较少吧
不过思路可以学习学习
1 楼 javne 2010-01-11  
但是类多了

相关推荐

    c#连接数据库常用的语句

    if (con.State == System.Data.ConnectionState.Closed) con.Open(); } catch (System.Data.SqlClient.SqlException E) { //如果出现错误,关闭数据连接,并抛出错误信息 this.Close(); throw new Exception...

    107个常用javascript语句

    14.JS中的判断语句结构:if(condition){}else{} 15.JS中的循环结构:for([initial expression];[condition];[upadte expression]) {inside loop} 16.循环中止的命令是:break 17.JS中的函数定义:function functionName...

    jsx-if:一个非常轻量级的助手,它向jsx添加了看起来很自然的条件

    JSX IF 一个非常轻量级的帮助程序,用于在JSX中编写具有本机外观的条件语句。...var _if = jsxIf._if, _elseif = jsxIf._elseif, _else = jsxIf._else;_if函数至少接受两个参数:条件和一个值或函数,如果为true

    vb学生成绩管理系统

    If ADOcn.State = adStateClosed Then ADOcn.Open '打开到数据库的连接 End Sub 完成本项工作后,就创建了一个全局变量ADOcn,但它是一个特殊的变量,其数据类型是数据连接对象(Connection对象)。可以把ADDcn理解...

    CMS.DBUtility.dll

    if ((Object.Equals(obj, null)) || (Object.Equals(obj, System.DBNull.Value))) { cmdresult = 0; } else { cmdresult = int.Parse(obj.ToString()); } if (cmdresult == 0) { return false; } else ...

    python实现在IDLE中输入多行的方法

    在python命令行模式下,在IDLE中输入多行,例如if else 使用tab的方式,控制缩进 在最后,连续两个回车,表示结束 &gt;&gt;&gt; if state: ... print "ok" ... else: ... print "wrong" ... wrong &gt;&gt;&gt; 以上这篇python实现...

    Java 2实用教程(第三版)实验指导与习题解答

    实验3 使用package语句与import语句 13 上机实践4 继承与接口 15 实验1 继承 15 实验2 上转型对象 17 实验3 接口回调 18 上机实践5 字符串、时间与数字 19 实验1 String类的常用方法 19 实验2 比较日期的大小 21 ...

    System.Data.Silverlight V2.0

    trans1.CommandText = "INSERT INTO [T_Message] ([Mobile],[Content],[DateTime],[PlatFlag],[State]) VALUES (@Mobile,@Content,@DateTime,@PlatFlag,@State)"; trans1.CommandType = DbCommandType.Text; ...

    android-template:具有各种通用组件的项目,以减少“项目设置”操作

    始终尝试使用单行if/else语句。 在那种情况下,不需要括号。 如果if/else表达式超过单行-请使用花括号。 如果仅使用if且表达式为单行-则不需要大括号。 private fun provideCardColor (): Int = if (x &gt; y) Color ...

    ZendFramework中文文档

    Querying if the input is valid 14.5.3.2. Getting Invalid, Missing, or Unknown Fields 14.5.3.3. Getting Valid Fields 14.5.4. Using Metacommands to Control Filter or Validator Rules 14.5.4.1. The ...

    API精灵源码(C#编)

    //查询语句 private string sql_update; private System.Windows.Forms.RichTextBox tipsmemo; private System.Windows.Forms.TextBox mat_text; private OleDbCommand mycommand = new OleDbCommand(); ...

    在PHP中输出JS语句以及乱码问题的解决方案

    if($state==0){ $classState=已下课; } else{ $classState=正在上课; } echo [removed] function getState(){ var cs = .$state.; return cs; } [removed]; ?&gt; 这样在页面的其他地方,就可以直接引用php中输出的...

    mysqlhelper

    if (conn.State == ConnectionState.Open) { conn.Close(); } conn.Open(); } /// /// 关闭数据库连接 /// public static void CloseConnect() { if (conn.State != ConnectionState.Closed) { conn...

    华为编程开发规范与案例

    软件编程规范培训实例与练习 ...if ( SPC_STATE_OK == pSpcCB-&gt;bySpcState ) 语句时,主机复位。但是该语句似乎并无不妥。 再分析整个函数,pSpcCB在函数前部分已经被赋值, pSpcCB = SpcCB + (PortTable...

    XML轻松学习手册--XML肯定是未来的发展趋势,不论是网页设计师还是网络程序员,都应该及时学习和了解

    单独用XMl不能显示页面,我们使用格式化技术,比如CSS或者XSL,才能显示XML标记创建的文档。 我们在前面第一章讲到XML是将数据和格式分离的。XML文档本身不知道如何来显示,必须有辅助文件来帮助实现。(XML取消了...

    oracle实验报告

    (5)在未使用显式游标的情况下,使用SELECT语句必须保证只有一条记录返回,否则会产生异常情况。 [例3-1] 问题:编写一个过程,求和运算。 SET SERVEROUTPUT ON; DECLARE a number:=1; BEGIN a:=a+5; DBMS_...

    java面试800题

    template模板方法模式、memento备忘录模式、observer观察者模式、command命令模式、state状态模式、strategy策略模式、mediator调停者模式、interpreter解释器模式、visitor访问者模式、chain of responsibility责任...

    最全的oracle常用命令大全.txt

    如果我们想知道user_indexes表各字段名称的详细含义,可以用下面这条SQL语句: SQL&gt;select column_name,comments from dict_columns where table_name='USER_INDEXES'; 依此类推,就可以轻松知道数据字典的详细...

    EDA课程设计

    else --以下case语句是程序中最关键的状态机部分 case state is when waitserve=&gt; --进程处于等待发球状态 case serve is when "10"=&gt; i;state; when "01"=&gt; i;state; when "11"=&gt;i; when others=&gt; i; end case; ...

    SQL sever 实训

    --使用ALTER TABLE 语句为已经创建的表添加主键约束、外键约束 --主键 ALTER TABLE Customer ADD CONSTRAINT PK_Customer PRIMARY KEY(CusNo) GO ALTER TABLE Product ADD CONSTRAINT PK_Product PRIMARY KEY...

Global site tag (gtag.js) - Google Analytics