使用状态模式(state pattern)替代if else

时间:2024-05-18 15:42:25

大多数开发人员现在还在使用if else的过程结构,曾看过jdonbanq大哥写的一篇文章,利用command,aop模式替代if else过程结构。当时还不太明白,这几天看了《重构》第一章的影片租赁案例,感触颇深。下面我来谈一谈为什么要用state pattern替代if else,替代if else有什么好处,以及给出详细代码怎么替代if else。本文参考jdon的“你还在使用if else吗?”及《重构》第一章。

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>

 

首先我们模仿影片租赁过程,顾客租凭影片,影片分为儿童片、普通片、新片。根据影片类型及租凭天数价格各不相同(优惠程度不同),用户累计积分不同。

 

OK ,现在我们使用 if else 表示。

使用状态模式(state pattern)替代if elsepackage  com.qujingbo.movie;
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
/** */ /**
使用状态模式(state pattern)替代if else * <p/> Title:影片基类
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Description:
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Date:2006-10-14 15:47:55
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * 
使用状态模式(state pattern)替代if else * 
@author  EOMS 曲静波
使用状态模式(state pattern)替代if else * 
@version  1.0
使用状态模式(state pattern)替代if else 
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
public   class  Movie  使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else     
//  普通片标识
使用状态模式(state pattern)替代if else
      public   static   int  REGULAR  =   1 ;
使用状态模式(state pattern)替代if else    
使用状态模式(state pattern)替代if else     
//  新片标识
使用状态模式(state pattern)替代if else
      public   static   int  NEW_RELEASE  =   2 ;
使用状态模式(state pattern)替代if else    
使用状态模式(state pattern)替代if else     
//  儿童片标识
使用状态模式(state pattern)替代if else
      public   static   int  CHILDREN  =   3 ;
使用状态模式(state pattern)替代if else    
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else     
/** */ /**
使用状态模式(state pattern)替代if else     * 获取租赁影片总价
使用状态模式(state pattern)替代if else     *
使用状态模式(state pattern)替代if else     * 
@param  movieCode
使用状态模式(state pattern)替代if else     * 影片类型
使用状态模式(state pattern)替代if else     * 
@param  days
使用状态模式(state pattern)替代if else     * 租凭天数
使用状态模式(state pattern)替代if else     * 
@return  租赁影片总价
使用状态模式(state pattern)替代if else     * 
@throws  MovieException
使用状态模式(state pattern)替代if else     * 没有影片类型抛出异常
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else     
public   double  getCharge( int  movieCode,  int  days)  throws  MovieException  使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     
double  result  =   0 ;
使用状态模式(state pattern)替代if else     
//  普通片
使用状态模式(state pattern)替代if else
      if  (movieCode  ==  Movie.REGULAR)
使用状态模式(state pattern)替代if else     
//  单价为2
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
      使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     result 
=   2 ;
使用状态模式(state pattern)替代if else     
//  如果租赁天数大于2则,则优惠
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
      if  (days  >   2 使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     result 
+=  (days  -   2 *   1.5 ;
使用状态模式(state pattern)替代if else     }

使用状态模式(state pattern)替代if else     
//  返回总价
使用状态模式(state pattern)替代if else
      return  result;
使用状态模式(state pattern)替代if else     }

使用状态模式(state pattern)替代if else     
//  最新发布片
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
      else   if  (movieCode  ==  Movie.NEW_RELEASE)  使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     
//  新片没有优惠,单价为3
使用状态模式(state pattern)替代if else
      return  days  *   3 ;
使用状态模式(state pattern)替代if else     }

使用状态模式(state pattern)替代if else     
//  儿童片
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
      else   if  (movieCode  ==  Movie.CHILDREN)  使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     
//  影片单价
使用状态模式(state pattern)替代if else
     result  =   1.5 ;
使用状态模式(state pattern)替代if else     
//  如果租赁时间大于3天则做价格优惠
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
      if  (days  >   3 使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     result 
+=  (days  -   3 *   1.5 ;
使用状态模式(state pattern)替代if else     }

使用状态模式(state pattern)替代if else     
//  返回租赁影片总价
使用状态模式(state pattern)替代if else
      return  result;
使用状态模式(state pattern)替代if else     }
  else
使用状态模式(state pattern)替代if else     
throw   new  MovieException( " 影片不存在 " );
使用状态模式(state pattern)替代if else     }

使用状态模式(state pattern)替代if else    
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else     
/** */ /**
使用状态模式(state pattern)替代if else     * 获取租赁影片积分
使用状态模式(state pattern)替代if else     *
使用状态模式(state pattern)替代if else     * 
@param  movieCode
使用状态模式(state pattern)替代if else     * 影片类型
使用状态模式(state pattern)替代if else     * 
@param  days
使用状态模式(state pattern)替代if else     * 租凭天数
使用状态模式(state pattern)替代if else     * 
@return  租赁影片积分
使用状态模式(state pattern)替代if else     * 
@throws  MovieException
使用状态模式(state pattern)替代if else     * 没有影片类型抛出异常
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else     
public   double  getIntegral( int  movieCode,  int  days)  throws  MovieException
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else     
使用状态模式(state pattern)替代if else {
使用状态模式(state pattern)替代if else     
//  普通片
使用状态模式(state pattern)替代if else
      if  (movieCode  ==  Movie.REGULAR)
使用状态模式(state pattern)替代if else     
return  days  *   2 ;
使用状态模式(state pattern)替代if else     
//  最新发布片
使用状态模式(state pattern)替代if else
      else   if  (movieCode  ==  Movie.NEW_RELEASE)
使用状态模式(state pattern)替代if else     
return  days  *   3 ;
使用状态模式(state pattern)替代if else     
//  儿童片
使用状态模式(state pattern)替代if else
      else   if  (movieCode  ==  Movie.CHILDREN)
使用状态模式(state pattern)替代if else     
return  days  *   1.5 ;
使用状态模式(state pattern)替代if else            
else
使用状态模式(state pattern)替代if else                
throw   new  MovieException( " 影片不存在 " );
使用状态模式(state pattern)替代if else    
使用状态模式(state pattern)替代if else        }

使用状态模式(state pattern)替代if else}

使用状态模式(state pattern)替代if else

OK ,我们看一下,现在的 Movie 完全符合租赁需求,通过 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 来获得租赁积分及租赁价格。从开闭原则角度来看,如果要添加新的影片类型,我们必须修改 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 这两个方法。而若要改变租赁价格、积分的优惠规则时,仍需要修改 getIntegral(int movieCode,int days) getCharge(int movieCode,int days) 方法。现在看来,只有三种影片类型,维护还较方便。而当影片类型较多时,例如 10 种, 100 种影片类型,这样就是不可以想像的维护。

 

现在我们来看一下,使用 state pattern 来代替 if else 。先来个类图。

 

使用状态模式(state pattern)替代if else 

首先我们建立一个 abstract class Price 做为影片类型的基类,基类中含有两个 abstract 方法,获取总价格 getCharge(int days), 获取总积分 getIntegral(int days) 方法 , 继承 abstract classPrice 的三个影片类型儿童片 class ChilerenPrice, 普通片 class RegularPrice, 最新片 class NewReleasePrice 。分别实现 getCharge(int days),getIntegral(int days) 方法,实现方法写入计算价格的优惠方案及积分的方案。当需要修改方案时,我们只需在某个影片类的方法中对应修改就可以。若新增一个影片分类时,我们只需新增一个实现类实现 abstract class Price 类就 OK

 

class Movie 代表影片,其关联一个 Price 类,而 setPrice(String movieClass) 方法类似于一个工厂类,传入 movieClass 为包名类名,用 java 反射机制实例化一个具体传入 movieClass 的影片类型实现类,这样我们通过这几行代码就可以获得该影片类型的价格和积分。

使用状态模式(state pattern)替代if elseMovie regularMovie  =   new  Movie();
使用状态模式(state pattern)替代if elseregularMovie.setPrice(Movie.REGULAR);
使用状态模式(state pattern)替代if elseSystem.out.println(
" 普通影片租赁10天的价格 " +  regularMovie.getPrice().getCharge( 10 ));
使用状态模式(state pattern)替代if elseSystem.out.println(
" 普通影片租赁10天的积分 " +  regularMovie.getPrice().getIntegral( 10 ));
使用状态模式(state pattern)替代if else

下面我们给出详细代码

abstract class Price价格基类

使用状态模式(state pattern)替代if elsepackage com.qujingbo.movie;
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
/** *//**
使用状态模式(state pattern)替代if else * <p/> Title:
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Description:
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Date:2006-10-14 15:48:22
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * 
使用状态模式(state pattern)替代if else * 
@author EOMS 曲静波
使用状态模式(state pattern)替代if else * 
@version 1.0
使用状态模式(state pattern)替代if else 
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
public abstract class Price 使用状态模式(state pattern)替代if else{
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
/** *//**
使用状态模式(state pattern)替代if else     * 获取租赁影片价格需实现该此方法
使用状态模式(state pattern)替代if else     * 
使用状态模式(state pattern)替代if else     * 
@param days
使用状态模式(state pattern)替代if else     *            租赁天数
使用状态模式(state pattern)替代if else     * 
@return 返回影片价格
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else    
public abstract double getCharge(int days);
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
/** *//**
使用状态模式(state pattern)替代if else     * 获取租赁影片积分需实现此方法
使用状态模式(state pattern)替代if else     * 
使用状态模式(state pattern)替代if else     * 
@param days
使用状态模式(state pattern)替代if else     *            租赁天数
使用状态模式(state pattern)替代if else     * 
@return 返回影片积分
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else    
public abstract double getIntegral(int days);
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else}

使用状态模式(state pattern)替代if else


儿童片ChildrenPrice类,实现abstract class Price ,实现儿童片租赁总价getCharge(int days)及儿童片租赁积分getIntegral(int days)
使用状态模式(state pattern)替代if elsepackage com.qujingbo.movie;
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
/** *//**
使用状态模式(state pattern)替代if else * <p/> Title:儿童片租赁积分、价格实现
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Description:
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Date:2006-10-14 15:49:04
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * 
使用状态模式(state pattern)替代if else * 
@author EOMS 曲静波
使用状态模式(state pattern)替代if else * 
@version 1.0
使用状态模式(state pattern)替代if else 
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
public class ChildrenPrice extends Price 使用状态模式(state pattern)替代if else{
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
/** *//**
使用状态模式(state pattern)替代if else     * 儿童片返回租赁积分,儿童片积分规则为: 根据
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
public double getIntegral(int days) 使用状态模式(state pattern)替代if else{
使用状态模式(state pattern)替代if else        
// 返回租赁影片积分
使用状态模式(state pattern)替代if else
        return days * 1.5;
使用状态模式(state pattern)替代if else    }

使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
/** *//**
使用状态模式(state pattern)替代if else     * 儿童片返回租赁价格
使用状态模式(state pattern)替代if else     
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else    
public double getCharge(int days) 使用状态模式(state pattern)替代if else{
使用状态模式(state pattern)替代if else        
// 影片单价
使用状态模式(state pattern)替代if else
        double result = 1.5;
使用状态模式(state pattern)替代if else        
// 如果租赁时间大于3天则做价格优惠
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
        if (days > 3使用状态模式(state pattern)替代if else{
使用状态模式(state pattern)替代if else            result 
+= (days - 3* 1.5;
使用状态模式(state pattern)替代if else        }

使用状态模式(state pattern)替代if else        
// 返回租赁影片总价
使用状态模式(state pattern)替代if else
        return result;
使用状态模式(state pattern)替代if else    }

使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else}

使用状态模式(state pattern)替代if else


普通片RegularlPrice类,实现abstract class Price ,实现普通片租赁总价getCharge(int days)及普通片租赁积分getIntegral(int days)

使用状态模式(state pattern)替代if elsepackage com.qujingbo.movie;
使用状态模式(state pattern)替代if else
使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
/** *//**
使用状态模式(state pattern)替代if else * <p/> Title:普通片租赁积分、价格实现
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Description:
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * <p/> Date:2006-10-14 15:50:10
使用状态模式(state pattern)替代if else * </p>
使用状态模式(state pattern)替代if else * 
使用状态模式(state pattern)替代if else * 
@author EOMS 曲静波
使用状态模式(state pattern)替代if else * 
@version 1.0
使用状态模式(state pattern)替代if else 
*/

使用状态模式(state pattern)替代if else使用状态模式(state pattern)替代if else
public class RegularlPrice extends Price 使用状态模式(state pattern)替代if else