策略模式 状态模式

当设计一个对象可能在不同情况下有不同的行为时,一般使用的是父类 子类 多态重载的方法,

Person a=new WhitePerson();

Person b=new BlackPerson();

a.speak();// i'm white

b.speak();// i'm black

但这样做不好的地方在于 假如对象创建后了之后想在运行时改变对象的行为是不可能的,(当然可以用if else判断状态值,但这样一、多次判断状态的话有重复代码  二、增加状态的时候增加else会违反开闭原则)除非重新创建对象,所以这时可以用策略分离行为

interface SpeakAction(){

  void speak();

}

 

class BlackSpeak implements SpeakAction(){

  void speak(){

    print "I'm black"

  }

}

 

class WhiteSpeak implements SpeakAction(){

  void speak(){

    print "I'm white"

  }

}

 

Person{

  SpeakAction speak;

 

  void speak(){

    speak.speak();

  }

 

  void setSpeak(SpeakAction speak){

    this.speak=speak;

  }

}

 

这样当你想改变行为的时候通过setSpeak设置新的行为就可以了

 

 

--------------------------------------------------------------------------------------------------

状态模式的类图和策略模式的类图很相似,都是面向一个接口有一系列不同的实现,然后调用的时候面向接口调用不同的实现;但是,策略模式和状态模式虽然类图上很相似,但是运用的时候,个人觉得有很大的区别,关键在于你在如何理解你的代码需求和设计要求,状态模式在gof的定义如下:

 

 

当一个状态的内部状态改变时允许改变其行为,这个对象看起来改变了其类;

 

状态模式主要突出了两个字:”改变”,对!对象的状态决定了状态的行为,事物的本质决定了事物的行为,我们精神亢奋的时候,我们拼命的工作,我们拼命的工作就导致了我们身心疲惫,物品们身心疲惫就导致我们的行为是需要休息;从这里我们可以看出,事物的内在状态决定了事物所做出的行为,而事物的行为势必又会改变我们事物的状态,两者在不断的相互影响,然后实现状态的迁移和跃迁;

 

从这两点,我们可以看出策略模式和状态模式的应用场景有很大的不同;一个是封装一系列平行且复杂多变的实现方式,一个是实现把对象的内在状态的变化封装起来,用外部行为来表现出来;

 

 

example:

----------------------------------------------------------------------------------

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

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

* 关于取钱操作的细节:
普通帐户每次取钱限额为1000元,不能透支
VIP帐户每次取钱限额为3000元,不能透支
信用卡帐户每次取钱限额为3000元,可以透支

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

* 帐号处于不同状态时对于上面提到的三种操作会产生影响:
新建状态时不能执行注销操作
挂失状态时不能执行存钱、取钱操作
冻结状态时不能执行存钱、取钱、注销操作

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

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

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

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

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

 

-------------------------------------------------------------------------------------------------

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

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

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

希望对你有帮助。


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值