处理对象的多种状态及其相互转换——状态模式(一)

转载 2013年12月06日 12:35:02

 “人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换。就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流动,冰可以雕刻,蒸汽可以扩散。我们可以用UML状态图来描述H2O的三种状态,如图1所示:

图1 H2O的三种状态(未考虑临界点)

       在软件系统中,有些对象也像水一样具有多种状态,这些状态在某些情况下能够相互转换,而且对象在不同的状态下也将具有不同的行为。为了更好地对这些具有多种状态的对象进行设计,我们可以使用一种被称之为状态模式的设计模式,本章我们将学习用于描述对象状态及其转换的状态模式。

 

1. 银行系统中的账户类设计

       Sunny软件公司欲为某银行开发一套信用卡业务系统,银行账户(Account)是该系统的核心类之一,通过分析,Sunny软件公司开发人员发现在该系统中,账户存在三种状态,且在不同状态下账户存在不同的行为,具体说明如下:

       (1) 如果账户中余额大于等于0,则账户的状态为正常状态(Normal State),此时用户既可以向该账户存款也可以从该账户取款;

       (2) 如果账户中余额小于0,并且大于-2000,则账户的状态为透支状态(Overdraft State),此时用户既可以向该账户存款也可以从该账户取款,但需要按天计算利息;

       (3) 如果账户中余额等于-2000,那么账户的状态为受限状态(Restricted State),此时用户只能向该账户存款,不能再从中取款,同时也将按天计算利息;

       (4) 根据余额的不同,以上三种状态可发生相互转换。

       Sunny软件公司开发人员对银行账户类进行分析,绘制了如图2所示UML状态图:

图2 银行账户状态图

       在图2中,NormalState表示正常状态,OverdraftState表示透支状态,RestrictedState表示受限状态,在这三种状态下账户对象拥有不同的行为,方法deposit()用于存款,withdraw()用于取款,computeInterest()用于计算利息,stateCheck()用于在每一次执行存款和取款操作后根据余额来判断是否要进行状态转换并实现状态转换,相同的方法在不同的状态中可能会有不同的实现。为了实现不同状态下对象的各种行为以及对象状态之间的相互转换,Sunny软件公司开发人员设计了一个较为庞大的账户类Account,其中部分代码如下所示:

[java] view plaincopy
  1. class Account {  
  2.     private String state; //状态  
  3.     private int balance; //余额  
  4.     ......  
  5.       
  6.     //存款操作    
  7.     public void deposit() {  
  8.         //存款  
  9.         stateCheck();     
  10.     }  
  11.       
  12.     //取款操作  
  13.     public void withdraw() {  
  14.         if (state.equalsIgnoreCase("NormalState") || state.equalsIgnoreCase("OverdraftState ")) {  
  15.             //取款  
  16.             stateCheck();  
  17.         }  
  18.         else {  
  19.             //取款受限  
  20.         }  
  21.     }  
  22.       
  23.     //计算利息操作  
  24.     public void computeInterest() {  
  25.         if(state.equalsIgnoreCase("OverdraftState") || state.equalsIgnoreCase("RestrictedState ")) {  
  26.             //计算利息  
  27.         }  
  28.     }  
  29.       
  30.     //状态检查和转换操作  
  31.     public void stateCheck() {  
  32.         if (balance >= 0) {  
  33.             state = "NormalState";  
  34.         }  
  35.         else if (balance > -2000 && balance < 0) {  
  36.             state = "OverdraftState";  
  37.         }  
  38.         else if (balance == -2000) {  
  39.             state = "RestrictedState";  
  40.         }  
  41.         else if (balance < -2000) {  
  42.             //操作受限  
  43.         }  
  44.     }  
  45.     ......  
  46. }  

       分析上述代码,我们不难发现存在如下几个问题:

       (1) 几乎每个方法中都包含状态判断语句,以判断在该状态下是否具有该方法以及在特定状态下该方法如何实现,导致代码非常冗长,可维护性较差;

       (2) 拥有一个较为复杂的stateCheck()方法,包含大量的if…else if…else…语句用于进行状态转换,代码测试难度较大,且不易于维护;

       (3) 系统扩展性较差,如果需要增加一种新的状态,如冻结状态(Frozen State,在该状态下既不允许存款也不允许取款),需要对原有代码进行大量修改,扩展起来非常麻烦。

       为了解决这些问题,我们可以使用状态模式,在状态模式中,我们将对象在每一个状态下的行为和状态转移语句封装在一个个状态类中,通过这些状态类来分散冗长的条件转移语句,让系统具有更好的灵活性和可扩展性,状态模式可以在一定程度上解决上述问题

 

【作者:刘伟 http://blog.csdn.net/lovelion

处理对象的多种状态及其相互转换——状态模式(五)

5 使用环境类实现状态转换        在状态模式中实现状态转换时,具体状态类可通过调用环境类Context的setState()方法进行状态的转换操作,也可以统一由环境类Context来实现...
  • wangeclipse
  • wangeclipse
  • 2013年12月07日 10:49
  • 412

处理对象的多种状态及其相互转换——状态模式(一)

“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换。就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流...
  • LoveLion
  • LoveLion
  • 2013年01月20日 22:34
  • 11302

处理对象的多种状态及其相互转换——状态模式(六)

6 状态模式总结        状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客...
  • wangeclipse
  • wangeclipse
  • 2013年12月07日 10:50
  • 387

处理对象的多种状态及其相互转换——状态模式(一)

“人有悲欢离合,月有阴晴圆缺”,包括人在内,很多事物都具有多种状态,而且在不同状态下会具有不同的行为,这些状态在特定条件下还将发生相互转换。就像水,它可以凝固成冰,也可以受热蒸发后变成水蒸汽,水可以流...
  • share_internet
  • share_internet
  • 2015年10月19日 17:32
  • 151

处理对象的多种状态及其相互转换——状态模式(三)

3 完整解决方案       Sunny软件公司开发人员使用状态模式来解决账户状态的转换问题,客户端只需要执行简单的存款和取款操作,系统根据余额将自动转换到相应的状态,其基本结构如图4所示:图4 银行...
  • LoveLion
  • LoveLion
  • 2013年01月20日 22:50
  • 7651

处理对象的多种状态及其相互转换——状态模式(六)

6 状态模式总结        状态模式将一个对象在不同状态下的不同行为封装在一个个状态类中,通过设置不同的状态对象可以让环境对象拥有不同的行为,而状态转换的细节对于客户端而言是透明的,方便了客户端...
  • xiangjie1991
  • xiangjie1991
  • 2013年05月29日 01:51
  • 556

处理对象的多种状态及其相互转换——状态模式(三)

3 完整解决方案        Sunny软件公司开发人员使用状态模式来解决账户状态的转换问题,客户端只需要执行简单的存款和取款操作,系统根据余额将自动转换到相应的状态,其基本结构如图4所示: ...
  • wangeclipse
  • wangeclipse
  • 2013年12月07日 10:48
  • 363

处理对象的多种状态及其相互转换——状态模式(四)

4 共享状态       在有些情况下,多个环境对象可能需要共享同一个状态,如果希望在系统中实现多个环境对象共享一个或多个状态对象,那么需要将这些状态对象定义为环境类的静态成员对象。 ...
  • share_internet
  • share_internet
  • 2015年10月19日 17:30
  • 166

处理对象的多种状态及其相互转换——状态模式(四)

4 共享状态      在有些情况下,多个环境对象可能需要共享同一个状态,如果希望在系统中实现多个环境对象共享一个或多个状态对象,那么需要将这些状态对象定义为环境类的静态成员对象。      下面通过...
  • LoveLion
  • LoveLion
  • 2013年01月20日 22:57
  • 6753

处理对象的多种状态及其相互转换——状态模式(二)

2 状态模式概述       状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。当系统中某个对象存在多个状态,这些状态之间可以进行转换,而且对象在不同状态下行为不相同时可以使...
  • share_internet
  • share_internet
  • 2015年10月19日 17:32
  • 167
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:处理对象的多种状态及其相互转换——状态模式(一)
举报原因:
原因补充:

(最多只允许输入30个字)