java设计模式6-模版方法模式

问题引入

豆浆制作问题

编写制作豆浆的程序

1、制作豆浆流程:选材--》添加配料--》放到豆浆机打磨

2、通过添加不同的配料,可以制作不同口味的豆浆

3、选材、浸泡和放入豆浆机这几个步骤对于制作每种口味的豆浆都是一样的

模版方法模式 

基本介绍

1、模版方法,又叫模版方法模式,在一个抽象类公开定义了指向它的方法的模版.它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行

2、简单说,模版方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构,就可以重定义该算法的某些特定步骤.

3、这种类型的设计模式属于行为型模式

类图

1、AbstractClass抽象类,类中实现了模版方法,定义了算法骨架,具体子类需要去实现其他的抽象方法operation1,2,3

2、ConcreteClass实现抽象方法operation1,2,3,以完成算法中特定子类的步骤

 

模版方法解决豆浆制作问题

思路

代码

//抽象类,表示豆浆
public abstract class SoyaMilk {

    //模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
    final void make() {

        select();
        addCondiments();
        soak();
        beat();

    }

    //选材料
    void select() {
        System.out.println("第一步:选择好的新鲜黄豆  ");
    }

    //添加不同的配料, 抽象方法, 子类具体实现
    abstract void addCondiments();

    //浸泡
    void soak() {
        System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
    }

    void beat() {
        System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");
    }
}
public class RedSoyaMilk extends SoyaMilk {

    @Override
    void addCondiments() {
        // TODO Auto-generated method stub
        System.out.println(" 加入上好的红豆 ");
    }

}
public class PeanutSoyaMilk extends SoyaMilk {

    @Override
    void addCondiments() {
        // TODO Auto-generated method stub
        System.out.println(" 加入上好的花生 ");
    }

}
public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //制作红豆豆浆

        System.out.println("----制作红豆豆浆----");
        SoyaMilk redBeanSoyaMilk = new RedSoyaMilk();
        redBeanSoyaMilk.make();

        System.out.println("----制作花生豆浆----");
        SoyaMilk peanutSoyaMilk = new PeanutSoyaMilk();
        peanutSoyaMilk.make();
    }

}

模版方法模式的钩子方法

1、在模版方法模式的父类中,我们可以定义一个方法,它默认不做任何事,子类可以视情况要不要覆盖它,这样的方法就是钩子方法

2、还是用上面做豆浆的例子,比如,我们还希望做纯豆浆,不添加任何配料,请使用钩子函数对前面的模版方法进行改造

代码

//抽象类,表示豆浆
public abstract class SoyaMilk {

    //模板方法, make , 模板方法可以做成final , 不让子类去覆盖.
    final void make() {

        select();
        if (customerWantCondiments()){
            addCondiments();
        }
        soak();
        beat();

    }

    //钩子方法,决定是否需要添加配料
    public boolean customerWantCondiments() {
        return true;
    }

    //选材料
    void select() {
        System.out.println("第一步:选择好的新鲜黄豆  ");
    }

    //添加不同的配料, 抽象方法, 子类具体实现
    abstract void addCondiments();

    //浸泡
    void soak() {
        System.out.println("第三步, 黄豆和配料开始浸泡, 需要3小时 ");
    }

    void beat() {
        System.out.println("第四步:黄豆和配料放到豆浆机去打碎  ");
    }
}
public class PureSoyaMilk extends SoyaMilk {

    @Override
    void addCondiments() {
        // TODO Auto-generated method stub
        //空实现
    }

    @Override
    //钩子方法,决定是否需要添加配料
    public boolean customerWantCondiments() {
        return false;
    }

}

模版方法在spring中的源码分析

1、SpringIOC容器初始化时运用到了模版方法模式

2、实现接口

注意事项和细节

1、基本思想:算法只存在于一个地方,也就是在父类中,容易修改.修改只需修改父类的模版方法,或者已经实现的步骤,子类就会继承这些修改

2、实现可最大化代码复用.父类的模版方法和已经实现的某些步骤会被子类继承而直接使用

3、父类的模版方法确保了算法结构的不变,同时由子类提供部分步骤的实现

4、该模式的缺点:每一个不同的实现都需要一个子类,导致类的个数增加,使得系统庞大 

5、一般模版方法都加上final关键字,防止子类重写模版方法

使用场景

a) 当要完成在某个过程,该过程要执行一系列步骤,且步骤基本相同,但个别步骤在实现时会不同,通常考虑使用模版方法

原文地址:https://www.cnblogs.com/Adam-Ye/p/13638784.html