template:模板
模板模式UML类图
角色
AbstractClass 抽象类实现了模板方法(template),定义了算法的骨架,具体子类需要去实现 其它的抽象方法 ConcreteClass 2)实现抽象方法 , 以完成算法中特点子类的步骤
案例
需求:统计某一代码运行时间
使用前
package com.javaxl.design.template.before;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-24 15:42
*/
public class CodeTotalTime {
public static void template(){
long start = System.currentTimeMillis();
// 检测Operation_1方法运行的时长======33
Operation_1();
// 检测Operation_2方法运行的时长======616
// Operation_2();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
public static void Operation_1(){
for (int i = 0; i<1000 ;i++){
System.out.println("模拟耗时操作...");
}
System.out.print("检测Operation_1方法运行的时长======");
}
public static void Operation_2(){
for (int i = 0; i<20000 ;i++){
System.out.println("模拟耗时操作...");
}
System.out.print("检测Operation_2方法运行的时长======");
}
}
public class Client {
public static void main(String[] args) {
CodeTotalTime.template();
}
}
使用后
package com.javaxl.design.template.after;
/**
* @author 小李飞刀
* @site www.javaxl.com
* @company
* @create 2020-02-24 15:51
* <p>
* 统计代码执行时长的抽象类
*/
public abstract class CodeAbstractClass {
public void template() {
long start = System.currentTimeMillis();
method();
long end = System.currentTimeMillis();
System.out.println("当前方法执行时长:"+(end - start));
}
public abstract void method();
}
class ConcreteClassA extends CodeAbstractClass{
@Override
public void method() {
for (int i = 0; i<1000 ;i++){
System.out.println("模拟耗时操作...");
}
System.out.print("检测ConcreteClassA.method方法运行的时长======");
}
}
class ConcreteClassB extends CodeAbstractClass{
@Override
public void method() {
for (int i = 0; i<20000 ;i++){
System.out.println("模拟耗时操作...");
}
System.out.print("ConcreteClassB.method方法运行的时长======");
}
}
public class Client {
public static void main(String[] args) {
//检测ConcreteClassA.method方法运行的时长======当前方法执行时长:40
// new ConcreteClassA().template();
//ConcreteClassB.method方法运行的时长======当前方法执行时长:272
new ConcreteClassB().template();
}
}
钩子函数应用场景:
public abstract class CodeAbstractClass {
public void template() {
long start = System.currentTimeMillis();
if (callback()) method();
long end = System.currentTimeMillis();
System.out.println("当前方法执行时长:" + (end - start));
}
public abstract void method();
public boolean callback() {
return true;
}
}
从上面可以看出:template方法默认是用作统计method方法的执行时长,但是有的时候我们无需统计代码时长,template函数中有一些其它逻辑要执行,在这里我们可以考虑采用钩子函数;钩子函数被子类覆写,覆写成false,那么method方法就不会被调用,不再统计代码时长了;前端框架Vue的生命周期就有多处用到钩子函数;
注意事项和细节
钩子函数 在模板方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,该方法称为“钩子”
算法只存在于一个地方,也就是在父类中,容易修改。需要修改算法时,只要修改父类的模板方法或者已经实现的某些步骤,子类就会继承这些修改
一般模板方法都加上 final 关键字, 防止子类重写模板方法
应用
Spring IOC容器加载
总结
模板非常容易理解,使用起来也很简单,但是在工程中我们往往将模板与其他模式结合起来,因此我们要认清模板的本质,将具有相同操作的多种事物抽象出这些相同的操作,然后将这些操作有机的整合起来变成模板类,另外也要注意在模板方法的定义final表示此方法不能被继承和重写,这无疑是重要的,规定和法则不能被其他人所改变。
备案号:湘ICP备19000029号
Copyright © 2018-2019 javaxl晓码阁 版权所有