定义一个操作中的算法的框架,而将一些步骤延迟到子类中,使得子类的可以不改变一个算法的结构即可重新定义该算法的某些特定的步骤。
- 多个子类有公有的方法,并且逻辑基本相同时。
- 重要、复杂的算法,可以把核心算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法模式是一个经常使用的模式,把相同的代码抽取到父类中,然后通过钩子函数约束其行为。
由上图,模板方法模式 主要包含这两种角色:
- AbstractClass(抽象类):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。
- 模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
- 基本方法:是整个算法中的一个步骤,包含以下几种类型。
- 抽象方法:在抽象类中申明,由具体子类实现。
- 具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
- 钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
- ConcreteClass(具体子类):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。
- 优点:
- 封装不变部分,扩展可变部分。
- 提取公共部分代码,便于维护。
- 缺点:
- 需要为每一个基本方法的不同实现提供一个子类,如果父类中可变的基本方法太多,将会导致类的个数增加,系统更加庞大,设计也更加抽象,此时,可结合桥接模式来进行设计。
- 工厂方法是模板方法的一种特殊版本。
- 策略模式和模板方法模式都是封装算法,一个用组合,一个用继承。
- 策略模式和模板模式通常可以互相替换。它们都像试卷,策略模式是选择题,模板模式是填空题。
模板方法模式用4个字概括就是:流程封装。也就是把某个固定的流程封装到一个final方法中,并且让子类能够定制这个流程中的某些或者所有步骤,这就要求父类提取公用的代码,提升代码的复用率,同时带来了更好的可扩展性。
在使用 AsyncTask 时,我们都知道把耗时操作放到 doInBackground 中,在 doInBackground 之前,如果想做一些初始化操作,可以把实现写在 onPreExecute 中,当 doInBackground 执行完后会执行 onPostExecute 方法,而我们只需要构建 AsyncTask 对象,然后执行 execute 方法。