问题梳理:

首先实现鸭子应用时用一个Duck抽象类,封装一些方法(飞,游泳)和一些抽象(外貌,叫)方法,然后用其他鸭子的子类来继承。这很好,但是后来新增一个鸭子子类,它不会飞,如果依然继承Duck类,就要覆盖父类的飞,进行重写,这样,每次新增鸭子,如果它有其他不同的地方,都要考虑要不要额外进行覆盖方法,而且,如果要修改现有的一个种类鸭子的其他方法,不能直接修改父类中继承的方法,这样会导致全部种类鸭子的改变,很不方便。由此得出,这样的设计方式有以下缺点:

  1. 代码在多个子类中重复。(有些子类并不需要父类的某些方法,但不得不重写它)
  2. 运行时的行为不容易改变。(编码完成后,鸭子的行为就定死了,面对实现编程)
  3. 很难知道所有鸭子的全部行为。(每个鸭子的行为都在类中重新覆盖,修改,很难观测,而且麻烦,混乱)
  4. 改变牵一发而动全身,造成其他鸭子不想要的改变。(更改父类,全部子类都会修改)

接下来考虑让经常改变的飞,叫的方法拿出来,做成接口,让其他鸭子来继承,这样有个优点是鸭子有什么功能可以区分出来,比较清晰,结果这样导致的后果是具有相同的这些功能的一种类,都必须在类中重新实现这些功能,导致代码的重复。

有没有对既有的代码影响最小的方式修改软件呢?有的。代码改造开始了

设计原则:

  1. 找出应用中可能需要变化之处,把它们独立出来,不要和那些不需要变化的代码混在一起。
  2. 针对接口编程,而不是针对实现编程。
    (注意:针对接口编程,并不是指java中的接口(java中只是恰好叫接口),而是像java中接口一样的抽象类,针对抽象类编程,执行时会根据实际状况执行到真正的行为,不会被绑死在超类型的行为上,放心的声明抽象类即可。)
  3. 多用组合,少用继承。
    (注意:使用组合建立系统偶很大的弹性,不仅可将算法zu封装成类,更可以“在运行时动态的改变行为”,只要组合的行为对象符合正确的接口标准即可。)

设计模式:

策略模式:

定义了算法族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。

最终设计: