第十篇:模板方法模式

    xiaoxiao2021-03-25  73

    我们先来谈谈 "模板" 的概念,什么是模板? 很简单嘛,直接上图!

    这就是一个模板!它定义了基本的样式,整个文档结构,内容大纲,而你要做的,就是再某些地方写上自己的内容就可以了! 让我们用代码来举一个模板方法的例子吧!

    我们拟定一个炒米粉的过程(因为我今天吃的是米粉),首先,要刷锅,然后放油,放入粉条,翻炒, 放盐,接下来可以选择放醋,放辣椒,放葱, 然后起锅放入碗中, 自此整个流程完毕!

    我们来分析一下这个过程:

    通过画图,我们发现,其中某些步骤是完全固定的,那我们就可以思考,是不是可以有一个类,然后定义一个总的方法,这个方法就像是一个大的算法(把炒米粉看成是一个算法吧)骨架,或者说它就是一个模板,在这个方法中,它顺序调用不同的方法(步骤) , 先调用刷锅(),再放油()...接下来要解决放粉条的问题,怎么办,它自己不知道要放什么粉条,OK,抽象嘛,让子类来决定要放什么粉条咯!  再接下来要放醋...到底放不放呢? 放醋的过程是固定的,我们要复用这段代码,那怎么办呢? 那具体放醋过程还是我们父类自己觉得,而到底要不要放我们则可以问一下子类嘛!当它回答说不放,那就不放!

    Ok,思路已经很清晰了!我们来让代码说话吧!

    先来几个面和粉的对象...

    /**所有粉条父类*/ public abstract class Flour { protected String name ; public String getName() {return name;} public void setName(String name) {this.name = name;} } /**挂面*/ class NoodlesFlour extends Flour{ public NoodlesFlour() { this.name = "挂面"; } } /**米粉*/ class RiceFlour extends Flour{ public RiceFlour() { this.name = "米粉"; } }  接下来定义我们的模板类!

    /**定义一个炒粉抽象模板方法类*/ abstract class AbstractFryFlourTemplate{ //定义为final,因为算法过程(炒粉过程)是固定的!我希望算法过程不被子类覆盖! public final void startFry(){ rinse(); addOil(); addFlour(); roll(); addSalt(); //仔细看看,这部分像不像是一个钩子? if( isAddVinegar() ){ addVinegar(); } if( isAddPepper() ){ addPepper(); } addToBowl(); } private final void rinse(){ System.out.println("刷锅..."); } private final void addOil(){ System.out.println("放点油..."); } //抽象方法,放入米粉 protected abstract void addFlour(); //翻炒方法,子类可以根据炒法不同而进行覆盖 protected void roll(){ System.out.println("默认慢慢的炒..."); } private final void addSalt(){ System.out.println("放点盐..."); } //放醋方法 private final void addVinegar(){ System.out.println("打开醋瓶"); System.out.println("放点醋..."); System.out.println("关好醋瓶"); } //放辣椒方法 private final void addPepper(){ System.out.println("放点辣椒!"); } private final void addToBowl(){ System.out.println("放到碗里去..."); } //到底放不放醋,子类可以来做决定,但我们默认放! protected boolean isAddVinegar(){ return true; } //到底放不放辣椒,必须子类做出决定,也就是必须问下客户,您要辣椒不? protected abstract boolean isAddPepper(); } 再定义两个不同的算法类...

    /**炒面的类*/ class FlyNoodlesFlour extends AbstractFryFlourTemplate{ @Override protected void addFlour() { Flour flour = new NoodlesFlour(); System.out.println("放入:"+flour.getName()); } //客人说要放辣椒 @Override protected boolean isAddPepper() { return true; } //覆盖翻炒方法,我是高级厨师... @Override protected void roll() { System.out.println("各种花样百出的炒..."); } } /**炒粉的类*/ class FlyRiceFlour extends AbstractFryFlourTemplate{ @Override protected void addFlour() { Flour flour = new RiceFlour(); System.out.println("放入:"+flour.getName()); } //客人说不要放辣椒 @Override protected boolean isAddPepper() { return false; } //客人还说也不要放醋 @Override protected boolean isAddVinegar() { return false; } } 测试一下:

    public class Test { public static void main(String[] args) { AbstractFryFlourTemplate aft = new FlyNoodlesFlour(); aft.startFry(); System.out.println("*****************************"); AbstractFryFlourTemplate aft2 = new FlyRiceFlour(); aft2.startFry(); } } 输出:*******************************************************************

    刷锅... 放点油... 放入:挂面 各种花样百出的炒... 放点盐... 打开醋瓶 放点醋... 关好醋瓶 放点辣椒! 放到碗里去... ***************************** 刷锅... 放点油... 放入:米粉 默认慢慢的炒... 放点盐... 放到碗里去...

    **************************************************************************

    Ok,我们来分析一下上面的代码吧!AbstractFryFlourTemplate类定义了一个统一的炒面粉的模板,可以把它看做事一个算法骨架,一个框架;  我们看到,它完成一个算法的流程是固定的,但某些流程它无法自己完成,所以定义为抽象的,让子类去完成, 更有趣的是,它定义了两个钩子方法,钩子方法有默认值,也就是这个算法默认就会这么去做,当然它也允许子类去决定到底要不要这样做,比如要不要放醋; 这一点,我们可以说成是, 通过定义钩子方法,模板类可以让子类参与和改变算法的某些执行过程!

    最后,我们来定义一下模板方法: 在一个方法中定义一个算法的骨架,但它允许将某些执行内容延迟到子类去执行; 通过钩子方法,它允许子类改变算法的执行过程!

    转载请注明原文地址: https://ju.6miu.com/read-35480.html

    最新回复(0)