深入浅出设计模式——模板方法模式

1.模板方法模式介绍
2.用代码演示模板方法模式
3.总结
4.在spring源码中,模板方法模式的应用
1.模板方法模式介绍
定义:
1)模板方法模式,在一个抽象类中公开定义了它的方法执行的模板,它的子类可以按需重写方法实现,但调用将以抽象类中定义的方式执行。
2)简单地说,模板方法模式定义一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重新定义该算法的某些特定步骤。
3)这种类型的设计模式属于行为模式。
2.用代码演示模板方法模式
假设我们有这样一个常见的需求:积分需求。简单地来说就是用户在消费的时候可以用积分抵扣金钱,如果交易成功还可以奖励积分,这就可以套用模板方法模式了。
我们可以将积分奖励/扣除的步骤分为三步

public interface IIntegralAction { //增加/扣除积分前的检查操作,如检查是否开户,检查用户是否异常,检查奖励/使用数是否异常等等 void preCheck(String userId); //执行具体的增减逻辑 void excute(String userId); //执行后置逻辑,如更新数据时间等等操作 void after(String userId); }

再定义一个抽象类,来实现这个抽象接口,并写好前置和后置的逻辑,设定好调用顺序。
public abstract class AbstractIntegralAction implements IIntegralAction {//到时候子类调用这个方法就可以了 public void excuteMethod(String userId){ this.preCheck(userId); this.excute(userId); this.after(userId); }@Override public void preCheck(String userId) { //写好前置逻辑 System.out.println("执行前置检查逻辑"); }@Override public void excute(String userId) { //交给子类去实现 }@Override public void after(String userId) { //写好后置逻辑 System.out.println("执行后置更新逻辑"); } }

调用方法:
public static void main(String[] args) { AbstractIntegralAction abstractIntegralAction = new AddIntegeralAction(); abstractIntegralAction.excuteMethod("1"); }

调用结果:
深入浅出设计模式——模板方法模式
文章图片

此时我们可能有疑问了,如果我某个实现类不想要前置检查方法怎么办?这个时候我们可以使用-----钩子方法
钩子方法介绍:
由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。
我们增加一个抽象方法:isOpenCheck,然后将该方法嵌入模板方法执行逻辑中。
public abstract class AbstractIntegralAction implements IIntegralAction {//到时候子类调用这个方法就可以了 public void excuteMethod(String userId){ //使用钩子方法确定是否要执行第一步 if(isOpenCheck()) { this.preCheck(userId); } this.excute(userId); this.after(userId); } //钩子方法 public boolean isOpenCheck(){ return true; }@Override public void preCheck(String userId) { //写好前置逻辑 System.out.println("执行前置检查逻辑"); }@Override public void excute(String userId) { //交给子类去实现 }@Override public void after(String userId) { //写好后置逻辑 System.out.println("执行后置更新逻辑"); } }

如果不需要第一步,子类覆盖之后返回false就可以了。
public class AddIntegeralAction extends AbstractIntegralAction{@Override public void excute(String userId) { System.out.println("增加积分的逻辑执行了"); }@Override public boolean isOpenCheck() { //不执行父类检查 return false; } }

执行结果:
深入浅出设计模式——模板方法模式
文章图片

3.总结
我们这就完成了模板方法设计模式,大部分人应该都用过,先将一个复杂的任务拆解成几个步骤,然后抽象出来,把相同的逻辑放在一起,不同的逻辑放在子类实现。
模板方法有以下几个部分组成:
抽象方法:需要子类去实现的具体逻辑,每个子类都不一样
模板方法:按照给定的执行顺序来进行执行
钩子方法:子类可以通过扩展钩子方法来影响模版方法的逻辑。
优点:
1)容易扩展,只需要新写类就行了,符合设计原则。
2)便于维护,需要变化的代码和不变的代码分离地清清楚楚。
3)灵活使用,使用钩子方法可以灵活应对
4)可读性高,一眼就能看穿代码的架构。
4.在spring源码中,模板方法模式的应用
我们可以尝试着在源码中搜索一下
ConfigurableApplicationContext 这个类

我们可以看出,它拥有很多抽象方法
深入浅出设计模式——模板方法模式
文章图片

是不是有点模板方法的味道了?
【深入浅出设计模式——模板方法模式】再看看AbstractApplicationContext这个实现类:
深入浅出设计模式——模板方法模式
文章图片

注解是我自己敲的,有兴趣的可以去我的github上下载:
https://github.com/su15967456...
我们看一下onRefresh() 这个方法,
深入浅出设计模式——模板方法模式
文章图片

像这个postProcessBeanFactory就是钩子方法,需要自己自己去实现的。

    推荐阅读