大多数开发人员现在还在使用if else的过程结构,曾看过jdon的banq大哥写的一篇文章,利用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
。先来个类图。
首先我们建立一个
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)。
相关推荐
### 状态模式(State Pattern) #### 概念与定义 状态模式是一种行为设计模式,它允许对象在其内部状态改变时改变其行为,使对象看起来像是修改了它的类。该模式通过引入一个代表各种状态的类以及一个行为随着这些...
状态模式的使用场景通常包括: - 当一个对象的行为取决于它的状态,并且它必须在运行时根据状态改变其行为时。 - 当你需要表示对象的所有可能状态,并且在这些状态之间的转换时。 - 当状态转换的逻辑复杂,且状态...
状态模式-State Pattern状态模式-State Pattern【学习难度:,使用频率:】状态模式-State Pattern处理对象的多种状态及其相互
在《设计模式》实战---状态模式(State Pattern)这篇文章中,作者可能详细探讨了以下关键点: 1. **模式定义**:状态模式允许对象在内部状态改变时改变其行为,对象看起来好像修改了它的类。这通过将每个状态封装...
状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式将一个对象的行为分解为各个独立的状态,并且每个状态都封装在自己的类中,使得对象在...
状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且根据不同的状态,对象的行为也相应地变化。在C++中实现状态模式,我们...
在软件设计领域,状态模式(State Pattern)是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。在这个案例中,“基于state pattern实现的xml解释器”指的是一个XML解析器,该...
因为我们经常会使用If elseif else 进行状态切换, 如果针对状态的这样判断切换反复出现,我们就要联想到是否可以采取State模式了. 不只是根据状态,也有根据属性.如果某个对象的属性不同,对象的行为就不一样,这点在...
状态模式定义Allow an object to alter its behavior when its internal state changes. The
状态模式是一种行为设计模式,它允许对象在内部状态改变时改变其行为,对象看起来似乎修改了它的类。这种模式常用于处理对象的状态变化,并且使代码结构清晰,易于维护。 在C++中,状态模式通常包含以下几个关键...
状态模式是一种行为设计模式,它使对象能够在内部状态改变时改变其行为,看起来好像改变了它的类。这种模式常用于处理对象在不同状态下表现各异的情况,避免了复杂的条件语句,提高了代码的可读性和可维护性。 在...
状态模式通常用于替代复杂的条件语句(如if...else...),使得代码更加清晰和易于管理。我们以登录状态为例来深入探讨这一模式。 在登录应用中,用户的状态主要有两种:未登录和已登录。在传统的编程方式中,我们会...
4. **替代大量条件分支语句**:通过状态模式,可以避免在上下文类中充斥着大量的if...else或者switch...case语句,提高了代码的可读性和可维护性。 然而,状态模式也有一定的缺点,如增加了系统类的数量,可能导致...
- 避免了条件分支语句:状态模式将与特定状态相关的行为封装到相应的状态对象中,消除了大量的if...else或switch语句,提高了代码的可读性和可维护性。 - 允许状态转换逻辑与状态对象绑定在一起,这使得增加新的状态...
在博文《Android的状态机模式StateMachine与State》中,作者可能会详细介绍如何创建和使用这两种组件。通常,状态机的实现会涉及到以下步骤: 1. **定义状态接口或抽象类**:创建一个State接口或抽象类,其中包含...
在某些情况下,大量使用if-else或switch语句会导致代码难以理解和维护,而状态模式则提供了一种优雅的解决方案。 总之,状态模式是一种强大的设计工具,它帮助我们在运行时动态地改变对象的行为,同时保持代码的...
如果我们经常使用 If-Else 语句来判断状态并进行切换,那么就可以考虑使用 State 模式。例如,在数据库系统中,某个对象的属性不同,对象的行为也不同,这时可以使用 State 模式来实现状态切换。 State 模式的优点...
2009-03-10模式State:一个事件(消息)引起环境或数据的变化,可能导致状态变化,于是处理流程改变,这里的状态是把处理流程分成了很多阶段,通过状态机来根据传来的事件(消息)引发状态转换,管理状态属性和状态行为,...
在订单状态管理中,状态机模式是一种常用的解决方案,但是在实际项目中,状态机的使用率并没有想象中那么高。笔者在电商领域进行后端开发时,发现了状态机的重要性,但是在使用 Spring StateMachine 时,发现了它的...
- 消除条件语句:原本可能需要大量if...else或switch...case语句来处理不同状态的情况,现在可以通过状态对象的调用来代替,使得代码更易于理解和维护。 然而,状态模式也有一些潜在的缺点,如增加系统类和对象的...