本篇博客的目录:
一:模板方法模式介绍
二:模板方法模式的简单实现
三:总结
一:模板方法模式的介绍
1.1:模板方法模式的定义
定义:一个操作中的算法的骨架,而将一些步骤延迟到子类中。TemplateMethod 使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
这句话的意思就是我们先定义一套固定的规则标准,然后让不确定的方法设置为抽象的,等到具体的实现时候,让子类再去实现。先设置好一套规则,定义好一套业务流程,再去具体实现。这就是模板方法。这和我们现实生活的许多做法有很多异曲同工之处,比如我们新职员入公司、去银行办理业务等等,它们都预先定制好了一套流程,我们要做的就是按照这个流程往下走,就可以完成这件事情。
1.2:结构以及介绍:
其中可以看到有一个抽象类,里面定义了几个操作方法和一个模板方法,然后具体的子类再去继承这个类,实现父类中尚未实现的方法。这其中还涉及一个概念,钩子方法,也称作回调函数(这个概念在jdbcTempalte中很常见).它的提出和模板方法设计的精髓很很大关联,抽象类中的抽象方法就是钩子,我们需要哪个挂哪个,再具体的去实现。
1.3:简单代码实现
为了让这个更具有说服力,我们来模拟一个流程,公司招聘新员工的业务流程。假如我现在要去公司应聘啦,公司肯定预先定制好了一套流程,我们用代码来仿照一下这个流程:
1.3.1:Company这个类定义为抽象类,我们预定了一系列的求职流程,求职者投递简历,决定是否通过,这里属于具体的实现细节,交给子类去实现。如果通过才能继续下面的流程,否则无法通过。然后就是会见求职者,笔试-面试,公司是否能让该求职者通过属于具体的子类实现细节,所以定义抽象方法isAccess(),只有在考虑录用的情况下才会发放offer,代码实现如下:
public abstract class Company { public static int score1=0; public static int score2=0; public void TemplateMethod(Jober jober){ if (Isreceive(jober)){ viewJober(jober); examination1(jober); examination2(jober); if (isAccess(jober)){ offer(jober); }else { System.out.println("很遗憾"+jober.getName()+"尚未通过本公司面试"); } }else { System.out.println(jober.getName()+"的简历不合格"); } } /** * 是否接受简历 * @return */ public abstract boolean Isreceive(Jober jober); /** * 会见求职者 * @param jober */ public void viewJober(Jober jober){ System.out.println("面试者会见求职者"+jober.getName()); } /** *笔试 * @param jober * @return */ public int examination1(Jober jober){ score1= jober.exam1(); return score1; } /** * 面试 * @param jober * @return */ public int examination2(Jober jober){ score2 = jober.exam2(); return score2; } /** * 考虑求职者是否能进入公司 * @param jober * @return */ public abstract boolean isAccess(Jober jober); /** * 发放offer * @param jober */ public void offer(Jober jober){ System.out.println("恭喜"+jober.getName()+"通过本公司的面试,现在发布offer"); } }
1.3.2:我们来定义一个具体的子类,去实现公司求职这个抽象父类,重写他的抽象方法,实现自己的逻辑:
public class AiLBaba extends Company { @Override public boolean Isreceive(Jober jober) { if ("Yrion".equals(jober.getName())) { System.out.println(jober.getName() + "通过本公司简历筛选"); return true; }else return false; } @Override public boolean isAccess(Jober jober) { if (score1+score2 > 150) return true; return false; } }
可以看到,我们只需要继承抽象的方法就行,这里的具体实现逻辑自己来决定,而整个求职过程不会变更,这也是模板方法的主要原则:
1.3.3 我们来定义一个求职者对象,主要作用就是调用求职公司的模板方法,发起一个流程:
public class Jober { private String name; public void setName(String name) { this.name = name; } public String getName() { return name; } public int exam1() { System.out.println(name + "正在笔试..."); return 88; } public int exam2() { System.out.println(name + "正在面试..."); return 90; } public void getJob(Company company){ company.TemplateMethod(this); } }
1.3.4:根据现实的规则,求职者应该是主动发起的,我们通过getJob方法向公司发起求职动作,公司已经预设好一系列的流程了,进而转为我们预先设计的模板流程中。好了,我们来建个测试类,运行这个小demo,看一下结果如何:
public class Test { public static void main(String[] args) { Company aLi =new AiLBaba(); Jober jober=new Jober(); jober.setName("Yrion"); jober.getJob(aLi); } }
运行结果如下:
Yrion通过本公司简历筛选 面试者会见求职者Yrion Yrion正在笔试... Yrion正在面试... 恭喜Yrion通过本公司的面试,现在发布offer
我们再来做个测试,假如尚未通过简历初选:
public class Test { public static void main(String[] args) { Company aLi =new AiLBaba(); Jober jober=new Jober(); jober.setName("周星星"); jober.getJob(aLi); } }
运行结果如下:
周星星的简历不合格
我们再来测试一下,假如简历通过,但是笔试面试尚未通过,只需要改这两处代码就行了:
public int exam1() { System.out.println(name + "正在笔试..."); return 60; } public int exam2() { System.out.println(name + "正在面试..."); return 60; }
我们再来测试一下:
Yrion通过本公司简历筛选 面试者会见求职者Yrion Yrion正在笔试... Yrion正在面试... 很遗憾Yrion尚未通过本公司面试
这个小实例就完成了,希望大家可以体会到模板方法的设计思想,进而将它运用到项目中去。这是个小实例,比较简单,接下来我们将会把目光转向更为复杂的Spring中的JDBCTemplate
三:总结
本篇博客讲解了Template设计模式,它的主要目标是减少工作量,把固定不变的步骤提取出来形成一个模板,然后具体的可变的部分再交给子类去实现,方便于日后的扩展,主要的适用性如下:
- 一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
- 各子类中公共的行为应被提取出来并集中到一个公共父类中以避免代码重复。首先识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
- 控制子类扩展。模板方法只在特定点调用,这样就只允许在这些点进行扩展。
预告:下篇博客,将会深入了解JDBCTempalte的设计源码