前语
看到规划形式中的模板形式(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 class FruitFactory {
public AbstractFruit getInstance(String fruit) {
if (fruit == null) {
return null;
}
if (fruit.equalsIgnoreCase("Apple")) {
return new Apple();
} else if (fruit.equalsIgnoreCase("Banana")) {
return new Banana();
} else if (fruit.equalsIgnoreCase("Watermelon")) {
return new Watermelon();
}
return null;
}
}
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的
感谢阅览~不喜勿喷。欢迎评论、指正