模板模式核心 - 钩子方法详解
前言
看到设计模式中的模板模式(Template Pattern),激动了
这题我会
模板模式定义👇
一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行
这核心不就是钩子方法嘛,我开发的时候还挺喜欢用的
欸嘿,看我把你说明白了
钩子方法
其实钩子方法的关键实现,在前言里已经说了,再复述一遍:
- 抽象类定义抽象方法(钩子)、模板方法(模板方法中调用抽象方法)
- 子类重写抽象方法
- 调用抽象类的模板方法
啥时候用呢
举个例子吧
有一次我们项目组收到需求,其中有个功能分析下来可以类比成这样:
- 苹果削皮吃
- 香蕉剥皮吃
- 西瓜切开吃
我对实现这个功能的小伙伴说,有成熟的技术大胆用,咱们总要进步的嘛
CodeReview的时候看到他整了个工厂模式
不错👏,听进去了
大致是这么写的
public abstract class AbstractFruit {
public abstract void eat();
}
public class Apple extends AbstractFruit {
@Override
public void eat() {
System.out.println("削皮吃");
}
}
public class Banana extends AbstractFruit {
@Override
public void eat() {
System.out.println("剥皮吃");
}
}
public class Watermelon extends AbstractFruit {
@Override
public void eat() {
System.out.println("切开吃");
}
}
public static void main(String[] args) {
FruitFactory fruitFactory = new FruitFactory();
AbstractFruit fruit = fruitFactory.getInstance("Apple");
fruit.eat();
}
后来有一天需求变了,“水果吃之前要洗一洗”
他说还行,改改 Apple、Banana、Watermelon 里的 eat() 就行
我说不用,改成钩子方法吧,省得用户“吃完水果还要扔垃圾”
他说啥叫钩子方法?
我说,你这样改
public abstract class AbstractFruit {
// 模板方法
public void eatFruit() {
// 通用逻辑
System.out.println("洗一洗");
// 模板方法调用钩子方法
this.eat();
}
// 钩子方法
public abstract void eat();
}
public static void main(String[] args) {
FruitFactory fruitFactory = new FruitFactory();
AbstractFruit fruit = fruitFactory.getInstance("Apple");
// 注意,这里由eat()改为了eatFruit()
fruit.eatFruit();
}
只能是抽象类、抽象方法吗
先说结论:不是。但得用Java8及以上版本
Java8新增了接口的默认方法
简单说,默认方法就是接口可以有实现方法,而且不需要实现类去实现其方法
所以说还可以用接口写
public interface IFruit {
default void eatFruit() {
System.out.println("洗一洗");
this.eat();
}
void eat();
}
public class Apple implements IFruit {
@Override
public void eat() {
System.out.println("削皮吃");
}
}
public class Banana implements IFruit {
...
}
public class Watermelon implements IFruit {
...
}
public static void main(String[] args) {
FruitFactory fruitFactory = new FruitFactory();
IFruit fruit = fruitFactory.getInstance("Apple");
fruit.eatFruit();
}
总结
通过例子我们可以看到当整体逻辑相同、部分逻辑有差异时,可以考虑使用钩子方法
另外说点题外话
我认为在开发时不用生搬硬套设计模式,没用到设计模式也不必妄自菲薄。开发是对需求的实现,跟着需求变化产出的代码就好。就像文中的例子,如果需求没变,那么工厂模式是完全OK的;如果“用户只吃一种水果”,那么不用工厂模式和钩子方法也是完全OK的
感谢阅读,不喜勿喷。欢迎讨论、指正
转载自:https://juejin.cn/post/7216894387993477181