[DesignPattern] 设计之禅读书笔记(五) 策略模式


  • 模板模式(Template Method Pattern)
    • Define the skeleton of an algorithm in operations, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure. (定义一个操作中的算法的框架, 而将一些步骤延迟到子类中。使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。)
    • 图例
    • AbstractClass(抽象模板)方法分两类:
      1. 基本方法:由子类实现,并在模板方法中被调用。这些方法一般尽量设计为protected.
      2. 模板方法:一个或几个具体的方法,也就是一个框架,实现对基本方法的调度,用来完成固定逻辑。为了防止恶意操作,一般模板方法都加上final关键字。不允许被覆写。
    • 优点:
      1. 封装不变部分,扩展可变部分。
      2. 提取公共部分代码,便于维护。
      3. 行为由父类控制,子类实现。
    • 缺点:
      • 一般抽象类负责声明最抽象,最一般的事务属性和方法,实现类来完成具体的属性方法。但是模板模式却颠倒了。抽象类定义了部分抽象方法,由子类实现,子类的执行结果影响了父类的结果,也就是子类对父类产生了影响。代码难度增加。
    • 使用场景:
      1. 多个子类有公有的方法,并且逻辑基本相同。
      2. 重要、复杂的算法,可以把核心算法设计为模板模式,周边相关细节功能则由各个子类实现。
      3. 重构时,模板方法使一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
    • 例子
    public abstract class AbstractClass {
      //基本方法
      protected abstract doSomething1();
      protected abstract doSomething2();
      //模板方法
      protected void templateMethod(){
        //调用基本方法完成相关逻辑
        this.doSomething1();
        this.doSomething2();
      }
    }
    
    public class ConcreteClass1 extends AbstractClass {
      //实现基本的方法
      protected void doSomething1(){
        //业务逻辑处理  
      }
      protected void doSomething2() {
      } 
    }
    
      public class ConcreteClass2 extends AbstractClass {
      //实现基本的方法
      protected void doSomething1(){
        //业务逻辑处理  
      }
      protected void doSomething2() {
      } 
    
      public class Client {
        public static void main(String args[]){
          AbstractClass class1 = new ConcreteClass1();
          AbstractClass class2 = new ConcreteClass2();
          //调用模板模式
          class1.templateMethod();
          class2.templateMethod();
        }     
      }
    }
    
    • 模板扩展
      • 钩子方法(Hook Method): 子类的一个返回值决定了公共部分的执行结果。
    • 最佳实践
      • 父类建立框架,子类在重写了父类部分的方法后,再调用从父类继承的方法,产生不哦她那个的结果。
      • 在一些开源框架中应用非常多,它提供了一个抽象类,然后开源框架写了一堆子类。如果你需要扩展功能,可以继承这个抽象类,然后覆写protected方法,再然后就是调用一个类似execute方法,就完成了你的扩展,非常容易扩展的一种模式