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");
    }

调用结果:
image.png

此时我们可能有疑问了,如果我某个实现类不想要前置检查方法怎么办?这个时候我们可以使用-----钩子方法

钩子方法介绍:

由抽象类声明并加以实现。但是子类可以去扩展,子类可以通过扩展钩子方法来影响模版方法的逻辑。

我们增加一个抽象方法: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;
    }
}

执行结果:

image.png

3.总结

我们这就完成了模板方法设计模式,大部分人应该都用过,先将一个复杂的任务拆解成几个步骤,然后抽象出来,把相同的逻辑放在一起,不同的逻辑放在子类实现。

模板方法有以下几个部分组成:

抽象方法:需要子类去实现的具体逻辑,每个子类都不一样
模板方法:按照给定的执行顺序来进行执行
钩子方法:子类可以通过扩展钩子方法来影响模版方法的逻辑。

优点:

1)容易扩展,只需要新写类就行了,符合设计原则。
2)便于维护,需要变化的代码和不变的代码分离地清清楚楚。
3)灵活使用,使用钩子方法可以灵活应对
4)可读性高,一眼就能看穿代码的架构。

4.在spring源码中,模板方法模式的应用

我们可以尝试着在源码中搜索一下

ConfigurableApplicationContext 这个类

我们可以看出,它拥有很多抽象方法

image.png

是不是有点模板方法的味道了?

再看看AbstractApplicationContext这个实现类:

image.png

注解是我自己敲的,有兴趣的可以去我的github上下载:

https://github.com/su15967456...

我们看一下onRefresh() 这个方法,

image.png

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


苏凌峰
73 声望38 粉丝

你的迷惑在于想得太多而书读的太少。