模板模式
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
介绍
意图:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
主要解决:一些方法通用,却在每一个子类都重新写了这一方法。
何时使用:有一些通用的方法。
如何解决:将这些通用算法抽象出来。
关键代码:在抽象类实现,其他步骤在子类实现。
应用实例: 1、在造房子的时候,地基、走线、水管都一样,只有在建筑的后期才有加壁橱加栅栏等差异。 2、西游记里面菩萨定好的 81 难,这就是一个顶层的逻辑骨架。 3、spring 中对 Hibernate 的支持,将一些已经定好的方法封装起来,比如开启事务、获取 Session、关闭 Session 等,程序员不重复写那些已经规范好的代码,直接丢一个实体就可以保存。
优点: 1、封装不变部分,扩展可变部分。 2、提取公共代码,便于维护。 3、行为由父类控制,子类实现。
缺点:每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
使用场景: 1、有多个子类共有的方法,且逻辑相同。 2、重要的、复杂的方法,可以考虑作为模板方法。
注意事项:为防止恶意操作,一般模板方法都加上 final 关键词。
角色
AbstractClass(抽象类):
在抽象类中定义了一系列基本操作(PrimitiveOperations),这些基本操作可以是具体的,也可以是抽象的,每一个基本操作对应算法的一个步骤,在其子类中可以重定义或实现这些步骤。同时,在抽象类中实
现了一个模板方法(Template Method),用于定义一个算法的框架,模板方法不仅可以调用在抽象类中实现的基本方法,也可以调用在抽象类的子类中实现的基本方法,还可以调用其他对象中的方法。
ConcreteClass(具体子类):
它是抽象类的子类,用于实现在父类中声明的抽象基本操作以完成子类特定算法的步骤,也可以覆盖在父类中已经实现的具体基本操作,一个模板方法是定义在抽象类中的、把基本操作方法组合在一起形成一个总算法或一个总行为的方法。这个模板方法定义在抽象类中,并由子类不加以修改地完全继承下来。模板方法是一个具体方法,它给出了一个顶层逻辑框架,而逻辑的组成步骤在抽象类中可以是具体方法,也可以是抽象方法。
基本方法是实现算法各个步骤的方法,是模板方法的组成部分。基本方法又可以分为三种:抽象方法(Abstract Method)、具体方法(Concrete Method)和钩子方法(Hook Method)。
- 抽象方法:一个抽象方法由抽象类声明、由其具体子类实现。
- 具体方法:一个具体方法由一个抽象类或具体类声明并实现,其子类可以进行覆盖也可以直接继承。
- 钩子方法:可以与一些具体步骤 “挂钩” ,以实现在不同条件下执行模板方法中的不同步骤
1 package com.java.template;
2
3 /**
4 * 模板方法模式
5 */
6 public class TemplateTest {
7
8 public static void main(String[] args) {
9 /*SubClass sc = new SubClass();
10 sc.getTime();*/
11
12 SubClass2 sc = new SubClass2();
13 sc.getTime();
14 }
15
16 }
17
18 //需求:计算一段程序的执行时间
19 abstract class Template {
20
21 // 钩子方法:可以提供实现,也可以不提供具体的实现
22 public void hook() {
23
24 }
25
26 /**
27 * 计算程序执行毫秒数【模板】
28 */
29 public void getTime() {
30
31 long start = System.currentTimeMillis();
32
33 // 内容区
34 code();
35
36 long end = System.currentTimeMillis();
37
38 System.out.println("耗费时间为:" + (end - start));
39
40 }
41
42 /*抽象模板方法*/
43 public abstract void code();
44 }
45
46 class SubClass extends Template {
47
48 @Override
49 public void code() {
50 for (int i = 0; i < 1000; i++) {
51 if (i % 2 == 0) {
52 System.out.println(i);
53 }
54 }
55 }
56 }
57
58 /**
59 * 【模板内容】
60 */
61 class SubClass2 extends Template {
62
63 @Override
64 public void hook() {
65 System.out.println("时间不够,代码来凑!");
66 }
67
68 @Override
69 public void code() {
70 for (int i = 0; i < 1000; i++) {
71 if (i % 2 != 0) {
72 System.out.println(i);
73 }
74 }
75
76 hook();
77 }
78
79 }