板方法模式:
模板方法模式是类的行为模式的一种,符合开闭原则(对扩展开放,对修改关闭)。创建一个规定了程序流程骨架的父类,并提供流程中需要个性化的方法供子类实现。还可以提取子类公共方法,以减少子类中的重复代码,并提高可复用性。
模板模式在Spring中运用就比较多了,比如IOC、再比如JdbcTemplate等等,运用还是比较广泛的,实现起来比较简单,理解也比较容易,还能美化代码结构,何乐而不为呢?
示例:
比如我们拿小朋友上学举个栗子,小朋友上学的时候都需要经过几个步骤:1.起床 2.洗漱 3.穿鞋 4.出门上学。所以这个是一个固定的流程,我们就拿这个来做示例,有个前提是小亮家新买了个玩具,而小黑没有买玩具(比较好学):
1.创建一个模板,上学的模版,里面定义好这几个步骤,然后规定了顺序,因为两人的情况不相同,所以各个方法都是等待子类实现:
public abstract class GoSchoolTemplate {
//起床
abstract void rise();
//洗漱
abstract void wash();
//穿鞋
abstract void shoes();
//上学
abstract void school();
public final void goSchool(){
rise();
wash();
shoes();
school();
}
}
2.然后编写小亮的上学流程,因为小亮有玩具,所以无论做什么都要玩一会儿玩具(其实是懒得想不同了),并去了第一幼儿园上学:
public class LiangTemplatePattern extends GoSchoolTemplate {
@Override
void rise() {
System.out.println("闹钟响了,小亮穿衣起床。。。(并玩了一会儿玩具)");
}
@Override
void wash() {
System.out.println("小亮开始洗漱。。。(并玩了一会儿玩具)");
}
@Override
void shoes() {
System.out.println("小亮开始穿鞋。。。(并玩了一会儿玩具)");
}
@Override
void school() {
System.out.println("小亮去实验第一幼儿园上学。。。");
}
}
3. 然后是小黑的,小黑没有玩具,所以就直接进行流程,然后去了第二幼儿园上学:
public class HeiTemplatePattern extends GoSchoolTemplate {
@Override
void rise() {
System.out.println("闹钟响了,小黑穿衣起床。。。");
}
@Override
void wash() {
System.out.println("小黑开始洗漱。。。");
}
@Override
void shoes() {
System.out.println("小黑开始穿鞋。。。");
}
@Override
void school() {
System.out.println("小黑去实验第二幼儿园上学。。。");
}
}
4.接下来运行一下看看效果:
//先贴上需要运行的代码
GoSchoolTemplate liang = new LiangTemplatePattern();
liang.goSchool();
GoSchoolTemplate hei = new HeiTemplatePattern();
hei.goSchool();
结果:
闹钟响了,小亮穿衣起床。。。(并玩了一会儿玩具)
小亮开始洗漱。。。(并玩了一会儿玩具)
小亮开始穿鞋。。。(并玩了一会儿玩具)
小亮去实验第一幼儿园上学。。。
闹钟响了,小黑穿衣起床。。。
小黑开始洗漱。。。
小黑开始穿鞋。。。
小黑去实验第二幼儿园上学。。。
发散:
以上基本的一个模板模式就已经实现了,然后接下来是一些优化,就是前言里所说的可以提取公共的方法。比如有一天小亮的父母发现了小亮洗漱的时候玩玩具会把玩具弄得很湿,然后就不让小亮在洗漱的时候玩玩具了。为什么弄得湿就不让玩了呢?嘿嘿嘿,我也不知道。那我们先进行程序改造吧:
1.小亮不在洗漱的时候玩玩具之后其实就和小黑没有任何区别了,那我们就可以把这块儿东西放在父类中,子类就可以少写一些代码了,先看父类,我们修改了一个抽象方法:
public abstract class GoSchoolTemplate {
//起床
abstract void rise();
//洗漱
private void wash(){
System.out.println("开始洗漱。。。");
}
//穿鞋
abstract void shoes();
//上学
abstract void school();
public final void goSchool(){
rise();
wash();
shoes();
school();
}
}
2.然后看小亮和小黑的类,我们删掉了原来的步骤:
public class LiangTemplatePattern extends GoSchoolTemplate {
@Override
void rise() {
System.out.println("闹钟响了,小亮穿衣起床。。。(并玩了一会儿玩具)");
}
@Override
void shoes() {
System.out.println("小亮开始穿鞋。。。(并玩了一会儿玩具)");
}
@Override
void school() {
System.out.println("小亮去实验第一幼儿园上学。。。");
}
}
public class HeiTemplatePattern extends GoSchoolTemplate {
@Override
void rise() {
System.out.println("闹钟响了,小黑穿衣起床。。。");
}
@Override
void shoes() {
System.out.println("小黑开始穿鞋。。。");
}
@Override
void school() {
System.out.println("小黑去实验第二幼儿园上学。。。");
}
}
3.然后再次看看运行结果,这次因为验证代码没有改动,就不进行粘贴,直接粘贴运行结果:
闹钟响了,小亮穿衣起床。。。(并玩了一会儿玩具)
开始洗漱。。。
小亮开始穿鞋。。。(并玩了一会儿玩具)
小亮去实验第一幼儿园上学。。。
闹钟响了,小黑穿衣起床。。。
开始洗漱。。。
小黑开始穿鞋。。。
小黑去实验第二幼儿园上学。。。
成功的改变了他们两个的实现。实现了提取公共的方法的操作,完成了一次代码结构的优化, 代码就看起来更赏心悦目了。当然还有一些其他的发散,比如直接在父类中写整个流程,还有具体实现。如果遇到私有的再去继承父类,重写父类中的方法等等,我就不再赘述,欢迎大家探讨。