Head First设计模式01 —— 策略模式

策略模式

问题

  • 为Duck超类扩展fly()方法,影响所有子类。可能使某些不适合子类(橡胶玩具鸭)具备该行为。

  • 继承

    • 使扩展牵一发动全身,父类改变造成子类不想要改变。
    • 运行时的行为不容易改变
  • 继承+重写

    • 代码冗余复杂,处理同一行为的不同表现时麻烦
    • 子类可以覆盖父类的方法,所以不知道子类的具体行为
  • 继承接口(Flyable)

    • 可以避免继承时的出现有不应具有的的行为而大量覆盖,在Java 8中可以用默认方法实现和继承效果一样的代码复用
    • 难以实现代码复用。某一行为在子类中都具有,却有不同实现时,仍然有代码重复的问题
    • 在获取到父类时,必须得先用instance of判断是否实现某接口,才能转换类型使用相关方法

[pAvct76.png

解决

  • 设计原则 - 开放封闭(对扩展开放,对修改封闭)
    • 把会变化的部分封装起来,减少其他部分影响。使变化引起不经意后果最小,增加系统弹性
  • 设计原则 - 针对接口编程,而非针对实现编程
    • 上述方法行为来自Duck超类的具体实现,或子类继承某个接口自行实现
    • 即“针对超类型 (supertype) 编程”, 可以在运行时动态改变实现
  • 多用组合,少用继承
    • 使用组合代码结构具有更大弹性,可以将算法族封装成类,并在运行时动态改变行为。动态改变实现

设计模式 - 策略模式

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

良好的OO设计具备的特性

  • 可复用
  • 可扩充
  • 可维护

应用

  • 优点
    • 支持开闭原则
      • 可以在不修改原有系统的基础上选择不同的行为,也可以额外扩展其它行为
    • 避免代码冗余
      • 避免使用多重条件判定语句
    • 安全保密
      • 终端使用策略不需要知道如何实现
  • 缺点
    • 策略类选择
      • 客户端必须知道所有策略类,并自行决定使用哪个策略
    • 增加复杂性
      • 如果系统复杂会产生很多策略类
  • 场景
    • 行为切换
    • 算法选择
      • JDK中的Arrays类的sort()方法可以动态地传入比较器
        • 通过传入不同的比较器实现算法的替换,而该变化独立于算法的使用者
      • org.springframework.beans.factory.support.InstantiationStrategy接口
        • 负责使用多种方法创建对应于根bean定义实例