`

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

阅读更多

大多数开发人员现在还在使用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 表示。

package  com.qujingbo.movie;

/** */ /**
 * <p/> Title:影片基类
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 15:47:55
 * </p>
 * 
 * 
@author  EOMS 曲静波
 * 
@version  1.0
 
*/

public   class  Movie  {

     
//  普通片标识
      public   static   int  REGULAR  =   1 ;
    
     
//  新片标识
      public   static   int  NEW_RELEASE  =   2 ;
    
     
//  儿童片标识
      public   static   int  CHILDREN  =   3 ;
    
     
/** */ /**
     * 获取租赁影片总价
     *
     * 
@param  movieCode
     * 影片类型
     * 
@param  days
     * 租凭天数
     * 
@return  租赁影片总价
     * 
@throws  MovieException
     * 没有影片类型抛出异常
     
*/

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

     
//  返回总价
      return  result;
     }

     
//  最新发布片
      else   if  (movieCode  ==  Movie.NEW_RELEASE)  {
     
//  新片没有优惠,单价为3
      return  days  *   3 ;
     }

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

     
//  返回租赁影片总价
      return  result;
     }
  else
     
throw   new  MovieException( " 影片不存在 " );
     }

    
     
/** */ /**
     * 获取租赁影片积分
     *
     * 
@param  movieCode
     * 影片类型
     * 
@param  days
     * 租凭天数
     * 
@return  租赁影片积分
     * 
@throws  MovieException
     * 没有影片类型抛出异常
     
*/

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

}


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 。先来个类图。

 

ifelse.jpg 

首先我们建立一个 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 的影片类型实现类,这样我们通过这几行代码就可以获得该影片类型的价格和积分。

Movie regularMovie  =   new  Movie();
regularMovie.setPrice(Movie.REGULAR);
System.out.println(
" 普通影片租赁10天的价格 " +  regularMovie.getPrice().getCharge( 10 ));
System.out.println(
" 普通影片租赁10天的积分 " +  regularMovie.getPrice().getIntegral( 10 ));

下面我们给出详细代码

abstract class Price价格基类

package com.qujingbo.movie;

/** *//**
 * <p/> Title:
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 15:48:22
 * </p>
 * 
 * 
@author EOMS 曲静波
 * 
@version 1.0
 
*/

public abstract class Price {

    
/** *//**
     * 获取租赁影片价格需实现该此方法
     * 
     * 
@param days
     *            租赁天数
     * 
@return 返回影片价格
     
*/

    
public abstract double getCharge(int days);

    
/** *//**
     * 获取租赁影片积分需实现此方法
     * 
     * 
@param days
     *            租赁天数
     * 
@return 返回影片积分
     
*/

    
public abstract double getIntegral(int days);

}



儿童片ChildrenPrice类,实现abstract class Price ,实现儿童片租赁总价getCharge(int days)及儿童片租赁积分getIntegral(int days)
package com.qujingbo.movie;

/** *//**
 * <p/> Title:儿童片租赁积分、价格实现
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 15:49:04
 * </p>
 * 
 * 
@author EOMS 曲静波
 * 
@version 1.0
 
*/

public class ChildrenPrice extends Price {

    
/** *//**
     * 儿童片返回租赁积分,儿童片积分规则为: 根据
     
*/

    
public double getIntegral(int days) {
        
// 返回租赁影片积分
        return days * 1.5;
    }


    
/** *//**
     * 儿童片返回租赁价格
     
*/

    
public double getCharge(int days) {
        
// 影片单价
        double result = 1.5;
        
// 如果租赁时间大于3天则做价格优惠
        if (days > 3{
            result 
+= (days - 3* 1.5;
        }

        
// 返回租赁影片总价
        return result;
    }


}



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

package com.qujingbo.movie;

/** *//**
 * <p/> Title:普通片租赁积分、价格实现
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 15:50:10
 * </p>
 * 
 * 
@author EOMS 曲静波
 * 
@version 1.0
 
*/

public class RegularlPrice extends Price color
分享到:
评论

相关推荐

    状态模式 State Pattern

    ### 状态模式(State Pattern) #### 概念与定义 状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。该模式通过引入一个代表各种状态的类以及一个行为随着这些...

    设计模式之状态模式(State Pattern)

    状态模式的使用场景通常包括: - 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。 - 当你需要表示对象的所有可能状态,并且在这些状态之间的转换时。 - 当状态转换的逻辑复杂,且状态...

    JackChan1999#Java-Degisn-Patterns#状态模式-State Pattern1

    状态模式-State Pattern状态模式-State Pattern【学习难度:,使用频率:】状态模式-State Pattern处理对象的多种状态及其相互

    《设计模式》实战---状态模式(State Pattern)

    在《设计模式》实战---状态模式(State Pattern)这篇文章中,作者可能详细探讨了以下关键点: 1. **模式定义**:状态模式允许对象在内部状态改变时改变其行为,对象看起来好像修改了它的类。这通过将每个状态封装...

    状态模式(State Pattern)是一种行为设计模式

    状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式将一个对象的行为分解为各个独立的状态,并且每个状态都封装在自己的类中,使得对象在...

    Head First 设计模式 (十) 状态模式(State pattern) C++实现

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且根据不同的状态,对象的行为也相应地变化。在C++中实现状态模式,我们...

    基于state pattern实现的xml解释器

    在软件设计领域,状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。在这个案例中,“基于state pattern实现的xml解释器”指的是一个XML解析器,该...

    设计模式State模式源码

    因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在...

    nevstop#LabVIEW-Design-Pattern#状态模式(State Pattern)1

    状态模式定义Allow an object to alter its behavior when its internal state changes. The

    设计模式C++学习之状态模式(State)

    状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且使代码结构清晰,易于维护。 在C++中,状态模式通常包含以下几个关键...

    设计模式之状态模式(State)

    状态模式是一种行为设计模式,它使对象能够在内部状态改变时改变其行为,看起来好像改变了它的类。这种模式常用于处理对象在不同状态下表现各异的情况,避免了复杂的条件语句,提高了代码的可读性和可维护性。 在...

    登录状态判断,使用状态模式

    状态模式通常用于替代复杂的条件语句(如if...else...),使得代码更加清晰和易于管理。我们以登录状态为例来深入探讨这一模式。 在登录应用中,用户的状态主要有两种:未登录和已登录。在传统的编程方式中,我们会...

    c++状态模式

    4. **替代大量条件分支语句**:通过状态模式,可以避免在上下文类中充斥着大量的if...else或者switch...case语句,提高了代码的可读性和可维护性。 然而,状态模式也有一定的缺点,如增加了系统类的数量,可能导致...

    C#面向对象设计模式纵横谈(22):(行为型模式) State 状态模式

    - 避免了条件分支语句:状态模式将与特定状态相关的行为封装到相应的状态对象中,消除了大量的if...else或switch语句,提高了代码的可读性和可维护性。 - 允许状态转换逻辑与状态对象绑定在一起,这使得增加新的状态...

    Android的状态机模式StateMachine与State

    在博文《Android的状态机模式StateMachine与State》中,作者可能会详细介绍如何创建和使用这两种组件。通常,状态机的实现会涉及到以下步骤: 1. **定义状态接口或抽象类**:创建一个State接口或抽象类,其中包含...

    设计模式的状态模式的例子

    在某些情况下,大量使用if-else或switch语句会导致代码难以理解和维护,而状态模式则提供了一种优雅的解决方案。 总之,状态模式是一种强大的设计工具,它帮助我们在运行时动态地改变对象的行为,同时保持代码的...

    试谈java设计模式之State.docx

    如果我们经常使用 If-Else 语句来判断状态并进行切换,那么就可以考虑使用 State 模式。例如,在数据库系统中,某个对象的属性不同,对象的行为也不同,这时可以使用 State 模式来实现状态切换。 State 模式的优点...

    每天感悟总结-状态模式State

    2009-03-10模式State:一个事件(消息)引起环境或数据的变化,可能导致状态变化,于是处理流程改变,这里的状态是把处理流程分成了很多阶段,通过状态机来根据传来的事件(消息)引发状态转换,管理状态属性和状态行为,...

    管理订单状态,该上状态机吗?轻量级状态机COLA StateMachine保姆级入门教程.doc

    在订单状态管理中,状态机模式是一种常用的解决方案,但是在实际项目中,状态机的使用率并没有想象中那么高。笔者在电商领域进行后端开发时,发现了状态机的重要性,但是在使用 Spring StateMachine 时,发现了它的...

    java设计模式之-状态模式-实现

    - 消除条件语句:原本可能需要大量if...else或switch...case语句来处理不同状态的情况,现在可以通过状态对象的调用来代替,使得代码更易于理解和维护。 然而,状态模式也有一些潜在的缺点,如增加系统类和对象的...

Global site tag (gtag.js) - Google Analytics