使用state pattern怎么在Java中实现if else功能
更新:HHH   时间:2023-1-7


使用state pattern怎么在Java中实现if else功能?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

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

首先我们建立一个 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 {
 /**
  * 普通片返回租赁积分,普通片积分规则
  */
 public double getIntegral(int days) {
  // 返回租赁影片积分
  return days * 2;
 }

 /**
  * 普通片返回租赁价格
  */
 public double getCharge(int days) {
  // 单价为2
  double result = 2;
  // 如果租赁天数大于2则,则优惠
  if (days > 2) {
   result += (days - 2) * 1.5;
  }
  // 返回总价
  return result;
 }

}

最新发布片NewReleasePrice类,实现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:48:51
 * </p>
 * 
 * @author EOMS 曲静波
 * @version 1.0
 */
public class NewReleasePrice extends Price {
 /**
  * 最新发布片返回租赁积分,最新发布片积分规则
  */
 public double getIntegral(int days) {
  // 返回租赁影片积分
  return days * 3;
 }

 /**
  * 最新发布片返回租赁价格
  */
 public double getCharge(int days) {
  // 新片没有优惠,单价为3
  return days * 3;
 }

}

电影Movie类,setPrice(String movieClass)(工厂)方法,通过java反射机制实现movieClass(包名,类名)类。若没有movieClass这个类,则抛出MovieException异常。

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 String REGULAR = "com.qujingbo.movie.RegularlPrice";

 // 新片标识
 public static String NEW_RELEASE = "com.qujingbo.movie.NewReleasePrice";

 // 儿童片标识
 public static String CHILDREN = "com.qujingbo.movie.ChildrenPrice";

 private Price price;

 public Price getPrice() {
  return price;
 }

 /**
  * 确定返回具体某个影片类型的实现类,有点像工厂
  * 
  * @param movieCode
  *   影片类型
  * @throws MovieException
  *    若无影片类型则抛异常。
  */
 public void setPrice(String movieClass) throws MovieException {
  try {
   Class cls = Class.forName(movieClass);
   this.price = (Price) cls.newInstance();
  } catch (Exception e) {
   throw new MovieException("影片不存在");
  }
 }
}

给出MovieException源码。

package com.qujingbo.movie;

/**
 * <p/> Title:自定义异常
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 19:21:08
 * </p>
 * 
 * @author EOMS 曲静波
 * @version 1.0
 */
public class MovieException extends Exception {
 public MovieException(String msg) {
  super(msg);
 }
}

下面模访一个顾客租赁影片。

package com.qujingbo.movie;

/**
 * <p/> Title:
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 19:26:23
 * </p>
 * 
 * @author EOMS 曲静波
 * @version 1.0
 */
public class Customer {
 /**
  * 消费(测试程序)
  * 
  * @throws MovieException
  *    若没有影片,抛出异常
  */
 public void consume() throws MovieException {
  // 普通电影
  Movie regularMovie = new Movie();
  regularMovie.setPrice(Movie.REGULAR);
  // 最新发布电影
  Movie newReleaseMovie = new Movie();
  newReleaseMovie.setPrice(Movie.NEW_RELEASE);
  // 儿童电影
  Movie childrenMovie = new Movie();
  childrenMovie.setPrice(Movie.CHILDREN);

  System.out.println("普通影片租赁10天的价格"
    + regularMovie.getPrice().getCharge(10));
  System.out.println("最新影片租赁10天的价格"
    + newReleaseMovie.getPrice().getCharge(10));
  System.out.println("儿童影片租赁10天的价格"
    + childrenMovie.getPrice().getCharge(10));
  
  System.out.println("普通影片租赁10天的积分"
    + regularMovie.getPrice().getIntegral(10));
  System.out.println("最新影片租赁10天的积分"
    + newReleaseMovie.getPrice().getIntegral(10));
  System.out.println("儿童影片租赁10天的积分"
    + childrenMovie.getPrice().getIntegral(10));
  
  
 }
}

写一 junit 测试类运行 class Customer 的 consume() 方法。

 package com.qujingbo.movie;

 import junit.framework.TestCase;

 /**
 * <p/> Title:junit测试类
 * </p>
 * <p/> Description:
 * </p>
 * <p/> Date:2006-10-14 19:32:57
 * </p>
 * 
 * @author EOMS 曲静波
 * @version 1.0
 */
 public class CustomerTest extends TestCase {

  private Customer customer = null ;

  protected void setUp() throws Exception {
   super .setUp();
  customer = new Customer();
 }

  protected void tearDown() throws Exception {
   super .tearDown();
 }

  /*
  * Test method for 'com.qujingbo.movie.Customer.consume()'
  */
  public void testConsume() {
   try {
   customer.consume();
  } catch (MovieException e) {
   System.out.println( " 没有该类影片 " );
  }
 }

}

OK 。结果为:

普通影片租赁 10 天的价格 14.0

最新影片租赁 10 天的价格 30.0

儿童影片租赁 10 天的价格 12.0

普通影片租赁 10 天的积分 20.0

最新影片租赁 10 天的积分 30.0

儿童影片租赁 10 天的积分 15.0

看完上述内容,你们掌握使用state pattern怎么在Java中实现if else功能的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注天达云行业资讯频道,感谢各位的阅读!

返回开发技术教程...