一、什么是模板方法模式?
???? 模板方法:定义了一套流程算法骨架,将一些固定的算法由抽象类定义,可变的部分延迟到子类中实现,同时可以定义一些钩子方法控制抽象类的操作。 模式的结构 1、抽象类(模板方法、抽象方法、具体方法、钩子方法) ???? 模板方法:定义具体操作流程,按某种顺序调用抽象方法、具体方法和钩子方法。 ???? 抽象方法:需要子类实现的方法。 ???? 具体方法:个流程相同的方法,由抽象类统一实现的。子类可以对其进行重写。 2、具体实现类 ???? 实现抽象类中的抽象方法。 ???? AbstractClass为抽象类,templateMethod()为抽象方法里面调用了具体方法(specificMethod())和抽象方法(abstractMethod()),SubClass为AbstractClass的子类实现了实现了抽象方法。ClientClass为客户类用于调用抽象类的模板方法。 UML图如下: 模板方法模式的优缺点 优点: ???? 1、将不变的部分封装到父类,可变部分由子类进行实现,便于子类进行扩展。 ???? 2、将公用部分统一由父类实现,提高了代码的复用性。 缺点: ???? 1、每个不同的实现都要增加类的个数,增加了系统的复杂程度,也增加了代码阅读的难度。 ???? 2、由于继承关系,父类增加抽象方法所有的子类都需要进行实现,所有子类都需要进行修改。
二、模板方法模式应用实例
???? 每个人的一天都是不同的,但具有相同部分例如起床、洗漱、吃早饭、完成上午的工作、午休、完成下午的工作、下班后的自由时间、晚上休息等。每天不同的地方在于上午的工作、下午的工作、下班后的自由时间所做的事情不同,其他基本是一样的。以一天为例实现一个简单的模板方法模式。 代码如下:
public class TestOneDay {
public static void main(String[] args) {
System.out.println("创建学生一天实例");
OneDayAbstract studentDay = new StudentDay();
System.out.println("执行学生的一天");
studentDay.run();
System.out.println("创建程序员一天实例");
OneDayAbstract programmerDay = new ProgrammerDay();
System.out.println("执行程序员的一天");
programmerDay.run();
}
}
public abstract class OneDayAbstract {
public void run(){
System.out.println("新的一天开始了!!!!");
System.out.println("时间:07:00");
up();
System.out.println("时间:09:00");
work1();
System.out.println("时间:11:30");
noonBreak();
System.out.println("时间:13:30");
work2();
System.out.println("时间:18:00");
anything();
System.out.println("时间:23:00");
sleep();
System.out.println("新的一天结束了!!!!");
}
public void up(){
System.out.println("起床!!!");
System.out.println("洗漱!!");
System.out.println("吃早饭!");
}
abstract void work1();
public void noonBreak(){
System.out.println("午休~");
}
abstract void work2();
abstract void anything();
public void sleep(){
System.out.println("休息!!!!!");
}
}
public class ProgrammerDay extends OneDayAbstract {
@Override
void work1() {
System.out.println("上午-敲代码!!!!");
}
@Override
void work2() {
System.out.println("下午-敲代码!!!!");
}
@Override
void anything() {
System.out.println("下班?不可能的。加班继续敲代码!!!!");
}
}
public class StudentDay extends OneDayAbstract {
@Override
void work1() {
System.out.println("上数学、语文、英语课!!!");
}
@Override
void work2() {
System.out.println("上物理、化学、生物课!!!");
}
@Override
void anything() {
System.out.println("晚自习拼命做题!!!");
}
}
执行结果如下: ???? 以学生和程序员为例实现了一天的抽象类。如果需要再添加一类人的一天则只需要集成抽象类并实现抽象方法就可以完成了,提高了开发效率。
模板方法模式拓展 ???? 抽象类中还有一类方法叫钩子方法,钩子方法一般是指判断的逻辑方法或者空方法由子类进行实现的,下面说明下钩子方法的使用。 一天的需求有变动,由于项目近期要上线需要赶工,程序员的午休时间取消了(程序员:mmp)。这时可以在抽象类的模板方法中增加判断逻辑。代码如下:
public abstract class OneDayAbstract {
public void run(){
System.out.println("新的一天开始了!!!!");
System.out.println("时间:07:00");
up();
System.out.println("时间:09:00");
work1();
System.out.println("时间:11:30");
if(haveNoonBreak()){
noonBreak();
}
System.out.println("时间:13:30");
work2();
System.out.println("时间:18:00");
anything();
System.out.println("时间:23:00");
sleep();
System.out.println("新的一天结束了!!!!");
}
public boolean haveNoonBreak(){
return true;
}
}
public class ProgrammerDay extends OneDayAbstract {
@Override
void work1() {
System.out.println("上午-敲代码!!!!");
}
@Override
void work2() {
System.out.println("下午-敲代码!!!!");
}
@Override
void anything() {
System.out.println("下班?不可能的。加班继续敲代码!!!!");
}
@Override
public boolean haveNoonBreak(){
return false;
}
}
修改后执行的结果如下: 增加了钩子方法后一般不会影响原有的实现类,因为钩子方法是默认实现的返回值为true。当返回值为true是模板方法的逻辑也没有发生变化,只有子类修改返回值为false时模板方法的逻辑才会发生变化。当然钩子的使用一般在程序设计时就已经添加在抽象类中了。
|