• 大话设计模式:模板方法模式


    什么是模板方法?即让工作或流程顺序按照写好的模板进行下去,同时还可以自定义流程,以及简化流程。

    举例:冲泡茶和咖啡均分四步进行:

    1. 把水煮沸
    2. 冲泡咖啡(茶)
    3. 把咖啡(茶)倒入杯子
    4. 加糖(柠檬)

    一般写法

    咖啡类

    public class Coffee {
    
        public void prepare() {
            /**
             * 制作咖啡:
             * 1。 把水煮沸
             * 2。 用水冲泡
             * 3。 把咖啡倒进杯子
             * 4。 加糖
             */
            boilWater();
            brewCoffee();
            pourInCup();
            addSuger();
        }
    
        public void boilWater() {
            System.out.println("把水煮沸");
        }
    
        public void brewCoffee() {
            System.out.println("用水冲泡咖啡");
        }
    
        public void pourInCup() {
            System.out.println("把咖啡倒进杯子");
        }
    
        public void addSuger() {
            System.out.println("加糖");
        }
    
    }
    

    茶类

    public class Tea {
    
        public void prepare() {
            /**
             * 制作茶:
             * 1。 把水煮沸
             * 2。 用水冲泡
             * 3。 把茶倒进杯子
             * 4。 加柠檬
             */
            boilWater();
            pourInCup();
            pourInCup();
            addLemon();
        }
    
        public void boilWater() {
            System.out.println("把水煮沸");
        }
    
        public void brewTea() {
            System.out.println("用水冲泡茶");
        }
    
        public void pourInCup() {
            System.out.println("把茶倒进杯子");
        }
    
        public void addLemon() {
            System.out.println("加柠檬");
        }
    
    }
    

    测试类

    public class Test01 {
    
        /**
         * 这种实现方式有很多重复的代码
         */
        public static void main(String[] args) {
            Coffee coffee = new Coffee();
            Tea tea = new Tea();
            coffee.prepare();
            System.out.println("---------------");
            tea.prepare();
        }
    
    }
    

    模板方法

    定义抽象的模板方法,把公共方法抽离出来,其它交给子类去实现

    public abstract class DrinksTemplate {
    
        /**
         * 设定为final,不让子类去覆盖或篡改流程
         */
        final public void prepare() {
            boilWater();
            brew();
            pourInCup();
            add();
        }
    
        public void boilWater() {
            System.out.println("把水煮沸");
        }
    
        /**
         * 交给子类实现
         */
        public abstract void brew();
    
        public void pourInCup() {
            System.out.println("把饮料倒进杯子");
        }
    
        public abstract void add();
    
    }
    

    咖啡类

    public class Coffee extends DrinksTemplate {
    
        @Override
        public void brew() {
            System.out.println("用沸水冲泡咖啡");
        }
    
        @Override
        public void add() {
            System.out.println("加糖");
        }
    }
    

    茶类

    public class Tea extends DrinksTemplate {
    
        @Override
        public void brew() {
            System.out.println("用沸水冲泡茶");
        }
    
        @Override
        public void add() {
            System.out.println("加柠檬");
        }
    }
    

    测试类

    public class Test01 {
    
        public static void main(String[] args) {
            Coffee coffee = new Coffee();
            Tea tea = new Tea();
            coffee.prepare();
            System.out.println("-----------");
            tea.prepare();
        }
    
    }
    

    使用钩子函数

    钩子函数是在抽象模板方法中定义的,它的作用就是控制流程中的某个步骤是否执行、简化流程,子类可以选择覆盖。比如,在准备给用户冲泡咖啡或茶之前询问用户是否需要加糖或者柠檬,不需要就不进行加糖或柠檬这一步骤了。

    抽象模板方法

    public abstract class DrinksTemplate {
    
        /**
         * 设定为final,不让子类去覆盖或篡改流程
         */
        final public void prepare() {
            boilWater();
            brew();
            pourInCup();
            if (ifAdd()) {
                add();
            }
        }
    
        public void boilWater() {
            System.out.println("把水煮沸");
        }
    
        /**
         * 交给子类实现
         */
        public abstract void brew();
    
        public void pourInCup() {
            System.out.println("把饮料倒进杯子");
        }
    
        public abstract void add();
    
        /**
         * 钩子函数
         */
        public Boolean ifAdd() {
            return true;
        }
    
    }
    

    只让茶类去覆盖钩子函数

    @Data
    public class Tea extends DrinksTemplate {
    
        private Boolean ifAdd;
    
        @Override
        public void brew() {
            System.out.println("用沸水冲泡茶");
        }
    
        @Override
        public void add() {
            System.out.println("加柠檬");
        }
    
        @Override
        public Boolean ifAdd() {
            return ifAdd;
        }
    }
    

    测试类

    @SuppressWarnings("Duplicates")
    public class Test01 {
    
        public static void main(String[] args) {
            Coffee coffee = new Coffee();
            Tea tea = new Tea();
            // 启用钩子函数
            tea.setIfAdd(false);
            coffee.prepare();
            System.out.println("==========");
            tea.prepare();
        }
    
    }
    

    测试结果

    把水煮沸
    用沸水冲泡咖啡
    把饮料倒进杯子
    加糖
    ==========
    把水煮沸
    用沸水冲泡茶
    把饮料倒进杯子
    
  • 相关阅读:
    mysqlsla 分析mysql慢查询日志
    MyBatis-DynamicSQL 动态SQL
    MyBatis-resultType 与 resultMap 中的几种返回类型
    MyBatis-${}与#{}
    MyBatis-parameterType 入参封装 Map 流程
    MyBatis-parameterType 取出入参值
    MyBatis-CURD
    第二十四篇-用VideoView制作一个简单的视频播放器
    第二十三篇-ubuntu18.04怎么下载播放器以及如何设置默认播放器
    第二十二篇-Guideline基准线
  • 原文地址:https://www.cnblogs.com/zhangjianbing/p/13654891.html
Copyright © 2020-2023  润新知