如何使用状态模式和策略模式消除if...else

06-09-21 Underwind

请教诸位这么一个问题,一个假象的银行帐户管理系统中:

* 帐户(Account)分为普通帐户,VIP帐户和信用卡帐户三种.

* 每个帐户都可以执行取钱,存钱,注销三种操作

* 关于取钱操作的细节:

普通帐户每次取钱限额为1000元,不能透支

VIP帐户每次取钱限额为3000元,不能透支

信用卡帐户每次取钱限额为3000元,可以透支

* 另外每个帐户有四种可能的状态:新建、正常、冻结、挂失

* 帐号处于不同状态时对于上面提到的三种操作会产生影响:

新建状态时不能执行注销操作

挂失状态时不能执行存钱、取钱操作

冻结状态时不能执行存钱、取钱、注销操作

这是简单的需求,在设计时,

* 我将帐户设置为抽象类(Account),普通帐户,VIP帐户和信用卡帐户为其子类

* 使用状态模式管理帐户的四种状态,具体做法为:建立接口AccountState,其中包含取钱,存钱,注销三个方法,然后给出四个实现类,分别对应新建、正常、冻结、挂失四种状态。在Accout中保持一个对状态的引用

问题:在实现状态模式中的三个方法的时候出现了问题,以取钱为例,显然取钱时要判断当前帐号的类别,这样一来难免引入if判断,二来需要在状态类中依赖Account子类,感觉并不好,请教好的解决思路。

(为了避免代码冗余,希望能用策略模式实现取钱,存钱等方法)

banq
2006-09-22 10:13

>以取钱为例,显然取钱时要判断当前帐号的类别,这样一来难免引入if判断,

这个问题是因为你状态设计有些问题,我培训时一直强调:使用状态模式之前一定要搞清楚事件和状态,这个案例中,取钱是个动作,无疑是事件,目前你的状态有新建、正常、挂失、冻结和注销四个状态,其他都是事件,你必须将这四个状态设为四个状态对象,事件导致状态变化,你要分析下这四个状态的切换是依靠什么事件完成的。

象取钱这样的事件,我目前发现不能造成上述四个状态的切换,所以,取钱应该写在普通的业务层里面,当然,为了封装只有正常状态才可以取钱这个规则,你可以在状态模式基础上再封装一层规则策略层,在其中将取钱规则写入,外部客户端调用时,只需传入事件特征如取钱,然后获得结果:要么正常;要么返回特定Exception,无法取钱。

至于if else只是一个设计结果的体现,可能会在规则策略层也用到if else,但是这时我的if else已经是一个非常简单,粒度很小的判断了,这就达到设计目的了。

希望对你有帮助。

二来需要在状态类中依赖Account子类,感觉并不好,