钩子方法

此处的钩子方法和Runtime类中的钩子线程是两种概念:Runtime.getRuntime( ).addShutdownHook( )

请参考:JVM钩子

钩子方法源于设计模式中模板方法(Template Method)模式,模板方法模式的概念为:在一个方法中定义一个算法骨架,而将一些具体步骤延迟到子类中实现。

模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤实现。其方法主要分为两大类:模版方法 和 基本方法,而基本方法又分为:抽象方法(Abstract Method),具体方法(Concrete Method),钩子方法(Hook Method)。

模板方法模式中的四种方法基本定义(前提:在抽象类中定义):

模板方法

​ 定义了一个方法,其中定义了整个逻辑的基本骨架。

抽象方法

​ 由抽象类声明,由具体子类实现,并以abstract关键字进行标识。

具体方法

​ 由抽象类声明并且实现,子类并不做实现和覆盖操作。其实质就是普遍适用的方法,不需要子类来实现。

钩子方法

​ 由抽象类声明并且实现,子类也可以选择重写加以扩展。

通常抽象类会给出一个空实现的钩子方法,也就是没有实现内容的扩展。它和具体方法在代码层面上没有区别,不过是一种意识的区别;它和抽象方法在子类中都需要实现的层面上也没有区别,不同的是抽象方法必须由子类实现,而钩子方法在子类中可以不实现。也就是说钩子方法为开发者在实现某一个抽象类的时候提供了可选项,相当于预先提供了一个默认配置。提供了更大的灵活性,有些抽象类的子类有很多,如果将方法定义成抽象方法,所有的子类都必须要实现,但该方法又不是所有子类都有的行为,如果只在对应的子类中进行具体实现,其他子类进行空实现,这样是可以的,但是无谓的工作量太多。此时就可以考虑使用钩子方法,在需要的子类中进行实现,不需要实现的子类中直接忽略。

示例代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* 抽象类,定义模板方法和基本方法
*/
abstract class AbstractClass {
/**
* 具体方法,声明并实现,继承此抽象类不需实现此方法
*/
public void concreteMethod() {
System.out.print("这是一个具体方法");
}

/**
* 抽象方法,abstract关键字标识,只声明,不实现,继承此抽象类的子类必须实现此方法
*/
protected abstract void abstractMethod();

/**
* 钩子方法,声明并实现(空实现或者定义相关内容皆可),继承此抽象类的子类可扩展实现或者不实现
*/
public void hookMethod() {
}

/**
* 模板方法,整个算法的骨架|场景:如解析所有的配置项,不同类型的配置项的解析方法不同,但是解析的流程是相同的,此时就可以将解析配置
* 抽象成一个类,将解析流程定义成一个模板方法,其中具体的解析方法由各个子类实现.
*/
public void templateMethod() {
abstractMethod();
concreteMethod();
hookMethod();
}
}

public class ChildClass {
public void bond(AbstractClass abstractClass) {
abstractClass.templateMethod();
}
}

class Test {
public static void main(String[] args) {
ChildClass childClass = new ChildClass();
childClass.bond(new AbstractClass() {
@Override
protected void abstractMethod() {
System.out.println("子类实现父类抽象类中的抽象方法");
}
});
}
}

接口中的default方法,也是一种钩子方法的思想。