zoukankan      html  css  js  c++  java
  • 策略模式——从鸭子入手

    一个鸭子类,子类有绿头鸭和红头鸭。



          每个鸭子都会叫,也会游泳,所以由超类来处理这些共同的东西。而display()方法是用来显示,更加直观的体现各部分的关系。

         当涉及维护时,为了复用而使用继承,问题往往更大。

         如果我们在Duck类中加一个fly()飞的方法,结果会怎么样?


          由于考虑不周,在Duck类中增加了fly(),这样ToyDuck玩具鸭子也继承了这个方法。可是事实上玩具鸭子是飞不起来的,那怎么办?类似的问题是,玩具鸭子只会吱吱地响,而不会向红头鸭那样呱呱的叫。

          这时,我们就要用“覆盖”了,将ToyDuck玩具鸭中的fly()方法覆盖掉,变成什么也不做,类似的,将quack()方法覆盖为吱吱叫。



          到这里,好像勉强是可以完成任务了。但当一个新的鸭子子类出现的话,我们都要考虑它是不是能飞,是不是能叫,是怎样飞的,怎样叫的。可见,这样的实现方法并不能一劳永逸。

          这时,我们可以考虑将一些容易或可能经常发生变化的一些方法,如fly,quack,从Duck抽象类中取出来,放到一个接口中,然后让会飞的绿头鸭、红头鸭去实现这个接口,而玩具鸭子就不去实现它了。


          引入接口之后,事情就方便多了,可这样一来,各个子类的代码就没办法复用了。

         找出可能变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。

         为了分开变化的和不变化的部分,需要建立两组类,一个是与fly相关的,一个是quack相关的,每组类各自实现各自的动作。我们将这两个行为从Duck类中分开,建立一组新类。

         针对接口编程,而不是针对实现。

         鸭子的子类将使用接口FlyBehavior和QuackBehavior所表示的行为,事实上的实现不会被绑死在鸭子的子类中。比如,玩具鸭子不能飞,这样的设计就可以在运行时动态的改变它的飞行行为。


    整合之后的全图就变成了下面的样子:


    由于精力有限,Duck中的部分地方没有说明。比如Duck类加了中两个实例变量 fly 和 quack,但并不影响理解。

    对比之前商场打折的例子:


          通过这两个例子,相信你会对策略模式有了更深入的理解。即使同样是理解了,总结与不总结收获差别蛮大的。

          顺着书上的思路走,虽然挺麻烦的,也走了弯路,但正是这样,才能更深刻的理解那些原则、经验。剩下要做的就是结合代码再重新梳理一下思路了。


  • 相关阅读:
    Microsoft.mshtml到底是什么?
    编译.NET程序自动产生版本号的规则
    VB.NET(2005)中关于dll调用的错误信息(转)
    C# RichTextBox控件 滚动条 自动移至 最后一条记录处
    如何刪除richtextbox最後一行
    Using Hudson for C++/CMake/CppUnit
    让开发自动化: 选择持续集成服务器
    C#加载窗体错误
    各种CI工具对比表
    用 Hudson 实现 Visual Studio (C++) 项目的 daily build
  • 原文地址:https://www.cnblogs.com/saixing/p/6730314.html
Copyright © 2011-2022 走看看