模版方法模式
来源:JS_HCX     阅读:558
灰太狼
发布于 2019-01-14 22:19
查看主页

模版方法模式

一、什么是模版方法模式

模板模式 :处理某类事情的步骤有些是固定的,有些是会发生变化的,那么这时候我们可以为这类事情提供一个模板代码,从而提高效率。

1.生活中的模版:

办理银行业务:

  1. 进门取号
  2. 填写单据(每个用户填写的单据都不一样,因业务不同而不同)
  3. 等待叫号
  4. 窗口办理

二、如何实现模版方法模式

1.模版方法模式的实现要素

准备一个笼统类,将部分逻辑以具体方法的形式实现,而后公告少量笼统方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模版方法。

2.模版模式的步骤

  1. 先写出处理该类事情其中 的一件的处理方案。
  2. 分析代码,把会发生变化的代码抽取出来独立成一个方法。把该方法形容成一个笼统的方法。
  3. 使用final修饰模板方法,防止别人重写你的模板方法。

3.具体实现

案例一:编写一个计算程序运行时间的模板。

笼统基类:

abstract class MyRuntime{        public final void getTime(){        long startTime = System.currentTimeMillis();    //记录开始的时间        code();        long endTime = System.currentTimeMillis();  //记录结束的时间.        System.out.println("运行时间 :"+ (endTime-startTime));    }    public abstract void code();}

具体子类:

class Demo extends MyRuntime{    public static void main(String[] args)     {        Demo d = new Demo();        d.getTime();    }    //code方法内部就写要计算运行时间的代码;    public  void code(){        int i = 0;        while(i<100){            System.out.println("i="+i);            i++;        }    }}

案例二:饮料的制法:

把水煮沸(boilWater)冲饮料(brew)把饮料倒进杯子(pourInCup)加调味料(addCondiments)

笼统基类:Drinks

package com.hcx.pattern.template;/** * 笼统基类,为所有子类提供一个算法框架 * 饮料 * @author HCX * */public abstract class Drinks {        /**     * 使用final修饰,防止子类改变模版方法     * 制备饮料的模版方法     * 封装了所有子类共同遵循的算法框架     */    public final void prepareDrinksTemplate(){        //步骤一:把水煮沸        boilWater();        //步骤二:冲饮料        brew();        //步骤三:把饮料倒进杯子        pourInCup();        //步骤四:加调味料        addCondiments();            }        /**     * 基本方法:把水煮沸     * 对所有子类,是一个共同的行为,不需要向子类开放;将变化的东西放在高层代码中。     */    private void boilWater() {        System.out.println("把水煮沸");    }    /**     * 基本方法:将饮料倒入杯中     */    private void pourInCup() {        System.out.println("将饮料倒入杯中");    }    /**     * 不同的情况,具体的实现不同,设计为笼统方法,需要在子类中可见,以便子类复写,提供具体的实现。     * 笼统的基本方法:加入调料     */    protected abstract void addCondiments();    /**     * 笼统的基本方法:泡饮料     */    protected abstract void brew();}

具体子类:Coffee

package com.hcx.pattern.template;/** * 具体子类,提供了咖啡制备的具体实现 * @author HCX * */public class Coffee extends Drinks {    @Override    protected void brew() {        System.out.println("用沸水冲泡咖啡");    }        @Override    protected void addCondiments() {        System.out.println("加入糖和牛奶");    }}

具体子类:OrangeJuice

package com.hcx.pattern.template;/** * 具体子类,提供了橙汁的具体实现 * @author HCX * */public class OrangeJuice extends Drinks{    @Override    protected void brew() {        System.out.println("准备橙子和榨汁机,把橙子丢入机器中榨汁");    }        @Override    protected void addCondiments() {        System.out.println("加入糖浆");    }}

测试:

package com.hcx.pattern.template;public class DrinksTest {        public static void main(String[] args) {        System.out.println("咖啡制备中");        Drinks drinks = new Coffee();        drinks.prepareDrinksTemplate();        System.out.println("咖啡好了");                System.out.println("*************************************");                System.out.println("橙汁制备中");        Drinks drinks2 = new OrangeJuice();        drinks2.prepareDrinksTemplate();        System.out.println("橙汁好了");    }}

结果:

咖啡制备中把水煮沸用沸水冲泡咖啡将饮料倒入杯中加入糖和牛奶咖啡好了*************************************橙汁制备中把水煮沸准备榨汁机和榨汁机,把橙子丢入机器中榨汁将饮料倒入杯中加入糖浆橙汁好了

使用钩子方法使代码更灵活:

在制备橙汁时,不想加入糖浆;

修改Drinks类,在加入调味料的步骤进行判断,编写钩子函数:

package com.hcx.pattern.template;/** * 笼统基类,为所有子类提供一个算法框架 * 饮料 * @author HCX * */public abstract class Drinks {        /**     * 使用final修饰,防止子类改变模版方法     * 制备饮料的模版方法     * 封装了所有子类共同遵循的算法框架     */    public final void prepareDrinksTemplate(){        //步骤一:把水煮沸        boilWater();        //步骤二:冲饮料        brew();        //步骤三:把饮料倒进杯子        pourInCup();                //步骤四:加调味料        if(wantCondiments()){            addCondiments();        }    }    /**     * Hook:钩子函数,提供一个默认或者空的实现     * 具体的子类可以自行决定能否挂钩以及如何挂钩,即能否重写父类的钩子函数     * 根据个人喜好,能否加入调料     * @return     */    protected boolean wantCondiments() {        return true;    }    /**     * 基本方法:把水煮沸     * 对所有子类,是一个共同的行为,不需要向子类开放;将变化的东西放在高层代码中。     */    private void boilWater() {        System.out.println("把水煮沸");    }    /**     * 基本方法:将饮料倒入杯中     */    private void pourInCup() {        System.out.println("将饮料倒入杯中");    }    /**     * 不同的情况,具体的实现不同,设计为笼统方法,需要在子类中可见,以便子类复写,提供具体的实现。     * 笼统的基本方法:加入调料     */    protected abstract void addCondiments();    /**     * 笼统的基本方法:泡饮料     */    protected abstract void brew();}

在OrangeJuice中重写钩子函数时:

package com.hcx.pattern.template;/** * 具体子类,提供了橙汁的具体实现 * @author HCX * */public class OrangeJuice extends Drinks{    @Override    protected void brew() {        System.out.println("准备橙子和榨汁机,把橙子丢入机器中榨汁");    }        @Override    protected void addCondiments() {        System.out.println("加入糖浆");    }        /**     * 重写父类的钩子方法     * 不加入任何调料,纯正的橙汁     */    @Override    protected boolean wantCondiments() {        return false;    }}

测试类打印结果:

咖啡制备中把水煮沸用沸水冲泡咖啡将饮料倒入杯中加入糖和牛奶咖啡好了*************************************橙汁制备中把水煮沸准备橙子和榨汁机,把橙子丢入机器中榨汁将饮料倒入杯中橙汁好了

总结:

模版模式总结.png

三、模版方法模式的适用场景及优缺点

适用场景:

优点:

缺点:

四、实例分析

分析解决各种日志

需求分析:

日志需求分析.png

可笼统为如下的步骤:

根据不同的情况,在变化部分的前后提供少量函数来提供扩展。

免责声明:本文为用户发表,不代表网站立场,仅供参考,不构成引导等用途。 系统环境 服务器应用
相关推荐
iOS 架构组件:让你的 TableView 优雅起来
让初学者不迷茫的Java学习方法有很多?
最美“侧脸杀”女程序媛:不拼颜值,拼代码
HBase实现社交关系数据存储
程序员私藏8个月年终奖被猎头老婆发现,上交后看到余额蒙了
首页
搜索
订单
购物车
我的