以租赁影片为例介绍使用state pattern替代if else
首先我们模仿影片租赁过程,顾客租凭影片,影片分为儿童片、普通片、新片。根据影片类型及租凭天数价格各不相同.
OK ,现在我们使用 if else 表示
public class Movie {
//普通片标识
public static int REGULAR = 1;
//新片
public static int NEW_RELEASE = 2;
//儿童片
public static int CHILDREN = 3;
//得到租赁的价格,movieCode影片类型 days天数
public double getCharge(int movieCode, int days) {
double result = 0;
if (movieCode == Movie.REGULAR) {
result = 2 * days;
//普通片大于2天优惠价格,超过2天的每天按1.5元算
if (days > 2) {
result = 2 * 2 + (days - 2) * 1.5;
}
return result;
} else if (movieCode == Movie.NEW_RELEASE) {
return days * 3;
} else if (movieCode == Movie.CHILDREN) {
result = 1.5 * days;
//儿童片大于3天优惠价格,超过3天的每天按1元算
if (days > 3) {
result = 1.5 * 3 + (days - 3) * 1;
}
return result;
}
return result;
}
}
我们看一下,现在的 Movie 完全符合租赁需求,通过 getCharge(int movieCode,int days) 来获得租赁积分及租赁价格。从开闭原
则角度来看,如果要添加新的影片类型,我们必须修改 getCharge(int movieCode,int days) 这两个方法.现在看来,只有三种影片
类型,维护还较方便。而当影片类型较多时,例如 10 种, 100 种影片类型,没种影片优惠的条件不一样,这样就是不可以想像的
维护。
我们看看采用 state pattern模式如何替代 if else
首先我们建立一个 abstract class Price 做为影片类型的基类,基类中含有abstract 方法,获取总价格 getCharge(int days),
继承 abstract classPrice 的三个影片类型儿童片 class ChilerenPrice, 普通片 class RegularPrice, 最新片 class
NewReleasePrice 。分别实现 getCharge(int days)方法,实现方法写入计算价格的优惠方案及积分的方案。当需要修改方案时,我
们只需在某个影片类的方法中对应修改就可以。若新增一个影片分类时,我们只需新增一个实现类实现 abstract class Price 类就
OK 。
lass Movie 代表影片,其关联一个 Price 类,而 setPrice(String movieClass) 方法类似于一个工厂类,传入 movieClass 为包
名类名,用 java 反射机制实例化一个具体传入 movieClass 的影片类型实现类,这样我们通过这几行代码就可以获得该影片类型的
价格和积分。
详细的类说明
Price类
package demo;
public abstract class Price {
public abstract double getCharge(int days);
}
ChildrenPrice类
package demo;
public class ChildrenPrice extends Price {
public ChildrenPrice() {
}
public double getCharge(int days) {
double result = 0;
//价格一天1.5元
result = 1.5 * days;
//普通片大于3天优惠价格,超过2天都按每天1元算
if (days > 3) {
result = 3 * 1.5 + (days - 3) * 1;
}
return result;
}
}
NewReleasePrice类
package demo;
public class NewReleasePrice extends Price{
public NewReleasePrice() {
}
public double getCharge(int days) {
return 3*days;
}
}
RegularlPrice类
package demo;
public class RegularlPrice extends Price{
public RegularlPrice() {
}
public double getCharge(int days) {
double result = 0;
//每天2元
result = 2 * days;
//普通片大于2天优惠价格,超过2天都按每天1.5元算
if (days > 2) {
result = 2 * 2 + (days - 2) * 1.5;
}
return result;
}
}
StateMovie类
package demo;
public class StateMovie {
public static String REG_CLASS="demo.RegularlPrice";
public static String CHI_CLASS="demo.ChildrenPrice";
public static String NEW_CLASS="demo.NewReleasePrice";
private Price price;
public StateMovie() {
}
public void setPrice(String movieClass){
try{
Class cls = Class.forName(movieClass);
this.price = (Price) cls.newInstance();
}catch(Exception ex)
{}
}
public double getPrice(int days)
{
return price.getCharge(days);
}
public static void main(String[] args)
{
StateMovie movie = new StateMovie();
movie.setPrice(StateMovie.REG_CLASS);
System.out.println(movie.getPrice(10));
}
}
如果需要增加新的影片,只需要增加新的类继承Price类,实现getCharge方法,然后在StateMovie类中增加一个新的Static类名就可以。用State 模式,无论你增加多少影片,修改思路相当简单,各影片计算方法互不影响。State模式,可以想想移动、电信的套餐是不是也可以用这种模式实现
OK ,现在我们使用 if else 表示
public class Movie {
//普通片标识
public static int REGULAR = 1;
//新片
public static int NEW_RELEASE = 2;
//儿童片
public static int CHILDREN = 3;
//得到租赁的价格,movieCode影片类型 days天数
public double getCharge(int movieCode, int days) {
double result = 0;
if (movieCode == Movie.REGULAR) {
result = 2 * days;
//普通片大于2天优惠价格,超过2天的每天按1.5元算
if (days > 2) {
result = 2 * 2 + (days - 2) * 1.5;
}
return result;
} else if (movieCode == Movie.NEW_RELEASE) {
return days * 3;
} else if (movieCode == Movie.CHILDREN) {
result = 1.5 * days;
//儿童片大于3天优惠价格,超过3天的每天按1元算
if (days > 3) {
result = 1.5 * 3 + (days - 3) * 1;
}
return result;
}
return result;
}
}
我们看一下,现在的 Movie 完全符合租赁需求,通过 getCharge(int movieCode,int days) 来获得租赁积分及租赁价格。从开闭原
则角度来看,如果要添加新的影片类型,我们必须修改 getCharge(int movieCode,int days) 这两个方法.现在看来,只有三种影片
类型,维护还较方便。而当影片类型较多时,例如 10 种, 100 种影片类型,没种影片优惠的条件不一样,这样就是不可以想像的
维护。
我们看看采用 state pattern模式如何替代 if else
首先我们建立一个 abstract class Price 做为影片类型的基类,基类中含有abstract 方法,获取总价格 getCharge(int days),
继承 abstract classPrice 的三个影片类型儿童片 class ChilerenPrice, 普通片 class RegularPrice, 最新片 class
NewReleasePrice 。分别实现 getCharge(int days)方法,实现方法写入计算价格的优惠方案及积分的方案。当需要修改方案时,我
们只需在某个影片类的方法中对应修改就可以。若新增一个影片分类时,我们只需新增一个实现类实现 abstract class Price 类就
OK 。
lass Movie 代表影片,其关联一个 Price 类,而 setPrice(String movieClass) 方法类似于一个工厂类,传入 movieClass 为包
名类名,用 java 反射机制实例化一个具体传入 movieClass 的影片类型实现类,这样我们通过这几行代码就可以获得该影片类型的
价格和积分。
详细的类说明
Price类
package demo;
public abstract class Price {
public abstract double getCharge(int days);
}
ChildrenPrice类
package demo;
public class ChildrenPrice extends Price {
public ChildrenPrice() {
}
public double getCharge(int days) {
double result = 0;
//价格一天1.5元
result = 1.5 * days;
//普通片大于3天优惠价格,超过2天都按每天1元算
if (days > 3) {
result = 3 * 1.5 + (days - 3) * 1;
}
return result;
}
}
NewReleasePrice类
package demo;
public class NewReleasePrice extends Price{
public NewReleasePrice() {
}
public double getCharge(int days) {
return 3*days;
}
}
RegularlPrice类
package demo;
public class RegularlPrice extends Price{
public RegularlPrice() {
}
public double getCharge(int days) {
double result = 0;
//每天2元
result = 2 * days;
//普通片大于2天优惠价格,超过2天都按每天1.5元算
if (days > 2) {
result = 2 * 2 + (days - 2) * 1.5;
}
return result;
}
}
StateMovie类
package demo;
public class StateMovie {
public static String REG_CLASS="demo.RegularlPrice";
public static String CHI_CLASS="demo.ChildrenPrice";
public static String NEW_CLASS="demo.NewReleasePrice";
private Price price;
public StateMovie() {
}
public void setPrice(String movieClass){
try{
Class cls = Class.forName(movieClass);
this.price = (Price) cls.newInstance();
}catch(Exception ex)
{}
}
public double getPrice(int days)
{
return price.getCharge(days);
}
public static void main(String[] args)
{
StateMovie movie = new StateMovie();
movie.setPrice(StateMovie.REG_CLASS);
System.out.println(movie.getPrice(10));
}
}
如果需要增加新的影片,只需要增加新的类继承Price类,实现getCharge方法,然后在StateMovie类中增加一个新的Static类名就可以。用State 模式,无论你增加多少影片,修改思路相当简单,各影片计算方法互不影响。State模式,可以想想移动、电信的套餐是不是也可以用这种模式实现