模板方法
概念:定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤
本质:分离算法,选择实现。即处理步骤父类中定义好,具体实现延迟到子类中定义
其实这个蛮好懂啦,设想一下,当你和某个老哥一起去银行办理业务,你办理贷款,他办理存款业务,一般来说,你们去了的第一件事情都是排队,轮到你们了你们再去办理各自要办理的业务,办理好后就离开。
如果用编程语言描述的话,应该是这样的
//办理贷款的你
public class You {
public void loan(){
//排队
queue();
//办理贷款业务中
loaning();
//走啦
leave();
}
public void queue(){
System.out.println("老子在排队,累死了");
}
public void loaning(){
System.out.println("穷成狗,想贷款..");
}
public void leave(){
System.out.println("溜了溜了");
}
}
//办理存款的老哥
class Laoge{
public void deposit(){
//排队
queue();
//办理贷款业务中
depositing();
//走啦
leave();
}
public void queue(){
System.out.println("老子在排队,累死了");
}
public void depositing(){
System.out.println("富得一批,赶紧存起来.");
}
public void leave(){
System.out.println("溜了溜了");
}
}
我们会发现,在这个过程中,你和这位老哥有一些一样的行为(排队和离开),也就是说You和Laoge中有两个共同的queue和leave方法。我们也已经学了这么久的设计模式了,相信现在多少有些感觉了,碰到这种有重复代码的,我们的第一感觉是有没有办法把这些相同的代码抽出来呢。哈哈,我们要介绍的模板方法模式,就可以比较优雅地实现我们的需求。
先大致讲一下思路吧,我们可以先定义一个抽象类,在该类中定义公有的行为(排队,离开),然后把办理的具体业务(贷款、存款)封装为一个抽象方法,由子类实现并定义具体的行为。在这个过程中,由于我们在抽象类中已经实现了公有的方法,所以You和Laoge(继承自抽象类)就只需要实现我们封装的那个方法就行啦!
实例
我们先定义个抽象类,
public abstract class Bank {
public void queue(){
System.out.println("老子在排队,累死了");
}
public abstract void transact();
public void leave(){
System.out.println("溜了溜了");
}
public final void process(){ //模板方法!!!
this.queue();
this.transact();
this.leave();
}
}
分类定义具体的子类,实现抽象方法
You
public class You extends Bank{
@Override
public void transact() {
System.out.println("穷成狗..要贷款哦");
}
}
Laoge
class Laoge extends Bank{
@Override
public void transact() {
System.out.println("富得一批,赶紧存起来.");
}
}
客户端测试
public static void main(String[] args) {
Bank you = new You();
you.process();
System.out.println(".....");
Bank laoge = new Laoge();
laoge.process();
}
优点
- 代码复用
- 开闭原则
缺点
- 每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。
应用场景
实现一个算法时,整体步骤很固定。但是,某些部分易变。易变部分可以抽象成出来,供子类实现。
实际应用
非常频繁。各个框架、类库中都有他的影子。比如常见的有:
数据库访问的封装
srpingJDBC
Junit单元测试
servlet中关于doGet/doPost方法调用
Hibernate中模板程序
spring中JDBCTemplate、HibernateTemplate等。