定义
在一个方法中定义了一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。
是一种重要的代码复用
的重要技巧。从实现的角度来说,这符合封装变化
的思想。同时,钩子
是被声明在抽象类中,但是只有空的
或者默认
的算法实现,由子类决定是否进行覆盖,对算法的不同点进行挂钩。当两个或多个类执行的操作可以抽象为统一的步骤算法,只是在每步细节的实现上有差异,则可以依赖模板方法构造一种继承体系(有变化就封装继承体系)
模板 = 方法 = 一组步骤(任何步骤都可以是抽象的,由子类负责实现)这可以确保算法的结构保持不变,同时由子类提供实现。
类图如下:
]
hook是对那些子类可以选择实现的功能,在抽像类中给出一个简单的默认实现,让子类决定去不去覆盖
这里涉及到两个角色:
抽象模板
- 定义了一个或多个抽象操作,以便让子类实现。这些抽象操作叫做基本操作,它们是一个顶级逻辑的组成步骤。
- 定义并实现了一个模板方法。这个模板方法一般是一个具体方法,它给出了一个顶级逻辑的骨架,而逻辑的组成步骤在相应的抽象操作中,推迟到子类实现。顶级逻辑也有可能调用一些具体方法。
具体模板
- 实现父类所定义的一个或多个抽象方法,它们是一个顶级逻辑的组成步骤。
- 每一个抽象模板角色都可以有任意多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法(也就是顶级逻辑的组成步骤)的不同实现,从而使得顶级逻辑的实现各不相同。
java
abstract class AbstractClass{ final void templateMethod(){ primitiveOperation1(); primitiveOperation2(); concreteOperation(); hook(); } // 声明为final 以免子类改变这个算法的顺序 abstract void primitiveOperation1(); // 子类实现 abstract void primitiveOperation2(); // 子类实现 void concreteOperation(){ } void hook(){} }
何时使用抽象方法?何时使用hook?
当你的子类必须提供算法中某个步骤的实现时,就用抽象方法;
如果算法中这个步骤是可选的,就用hook. 通过使用钩子,让抽象类的子类的负荷减轻itu