软考:策略VS状态

来源:互联网 发布:怎么读源码 编辑:程序博客网 时间:2024/06/04 00:27

策略模式:     

        策略模式封装不同算法家族,让他们之间相互替换,保证算法的变化独立于使用算法的客户。从鸭子实例可以看出策略是如何封装变化,如何使用组合,如何针对接口编程的。

第一版:

    

        每个鸭子子类都继承超类,结果是所有鸭子都会游泳、都会呱呱叫。如果有的鸭子会飞呢,只能在超类中添加fly()行为,所以说使用继承达到复用目的并不完美了。如果来一个橡皮鸭呢?只会只会吱吱叫;再或者还有一个木头鸭不会叫也不会飞?这是有人想到用橡皮鸭的吱吱叫覆盖超类中的呱呱叫,还有人把fly()quack()从超类抽象出来放进Flyable接口(只有会飞的才会实现此接口)和Quackable接口(只有呱呱叫实现该接口)。

第二版:


        因为并非所有鸭子都会飞行和呱呱叫,所以继承不是适当方式,虽然抽象接口可以解决其中问题(不会出现会飞的橡皮鸭),但是会出现大量重复代码,这时策略出现。

第三版:

        将应用中可能需要变化的独立出来,fly()quack()会随着鸭子的不同而改变,所以将这两个行为从Duck类中分开,建立一组新类代表每个行为。如果想要指定行为到鸭子实例,最好在鸭子类中包含设定行为的方法,然后可以在运行时动态的改变鸭子的行为。鸭子的子类使用接口FlyBehavior所表示行为,所以实际的实现不会被绑死在鸭子子类中(之前做法:行为来自鸭子超类具体实现,或继承某个接口由子类自行实现,这两种做法都依赖于“实现”,被实现绑的死死的,没办法更改行为,除非写更多代码)。


        具体实现:Duck中添加flyBehaviorquackBehavior两个实例变量,运行时持有特定行为引用,鸭子子类中实例化具体的行为,比如绿头鸭呱呱叫行为就委托给Quack对象,客户端如果要一个呱呱叫会飞的绿头鸭,先实例化一个对象,然后直接调用Duck的方法即可,因为子类继承Duck,而子类中已经实例化一个具体行为,所以客户端通过组合便可以得到自己想要的任何效果。

状态模式:

    它通过改变对象内部的状态来帮助对象控制自己的行为,对象看起来好像修改了它的类。


    在糖果机开始设计时,是针对行为封装的,比如插入硬币、退回硬币、转动曲柄和发放糖果,然后判断他们有可能出现的状态,但是如果添加一种新的状态,这时每个类都有修改。

        这时有了新的设计:将状态对象封装起来,首先定义一个State接口,糖果机的每个动作对应一个方法,然后为糖果机每个状态都封装成一个类,添加对糖果机的引用作为类中方法的参数,实现State接口。在糖果机类中放置所有的状态和实例变量state,每种状态也都创建一个状态实例,那些行为的实现就会委托给当前状态。具体的状态处理来自糖果机的请求,它里面提供了对于请求的实现,所以当糖果机改变状态时行为也跟着改变。这样将每个状态行为局部化到自己类中,也删除了if ...else语句,让每个状态对修改关闭,让糖果机对扩展开放。

策略VS状态:

       因为两设计模式类图很类似,只是侧重不同。策略中客户通常主动指定Context所要组合的策略对象,而且通常只有一个最合适的,比如绿头鸭就是呱呱叫,用翅膀飞翔,所以可以通过组合对象改变行为。而状态是将一群行为封装在状态中,可以通过Context简单修改状态对象来改变其行为,Context的行为随时可以委托到状态中的一个,但是客户对状态对象了解很少。

0 0
原创粉丝点击