• 设计模式学习 —— 模板方法


    设计模式学习 —— 模板方法

    模板模式:封装了一个算法步骤,并允许子类为一个或者多个步骤方法提供实现。模板模式可以在子类不改变算法结构的情况下,重新定义算法中的某些步骤。

    固定的东西成为模板在抽象父类中。

    个性化的步骤在子类中实现。

    身边的模板模式:
    我们用的很多框架都是用模板来完成的:
    1、排序鸭子 :Arrays.sort() 这个就是个模板方法,Ducks 这个类实现 Comparable 接口
    2、自定义控件
    3、

    编写模板方法类

    要点:1、设计成抽象类的原因是这个类中有未实现的方法,之所以不设计成接口,是因为这个类中有固定实现的方法(是不是 Java8 中可以用接口来实现,因为 Java8 有接口默认实现方法);
    2、整个模板方法 prepareBeverageTemplate() 设计成 final ,体现了模板的固定性。
    既然叫“模板”,意思是按照固定的模式去做一件事情,所以模板这件事情上不能留给客户端空间,否则就失去了模板的意义。
    3、固定的步骤,已经实现的方法,使用 private 修饰,子类不能修改,这一部分是模板类中固定的部分;
    4、须要让子类完成的步骤,应该使用 protected 修饰,延迟到子类实现;
    5、关注到钩子函数,钩子函数使用 protected 修饰,并且不是抽象的方法,是一个具体的方法,子类可以根据须要去重写。

    /**
     * Created by Liwei on 2016/7/4.
     * 抽象基类,为所有子类提供一个算法框架
     * 提神饮料
     */
    public abstract class RefreshBeverage {
    
        /**
         * 制备饮料的模板方法
         * 封装了所有子类共同遵循的算法框架
         */
        public final void prepareBeverageTemplate() {
            // 步骤 1 将水煮沸
            boilWater();
            // 步骤 2 泡制饮料
            brew();
            // 步骤 3 将饮料倒入杯中
            pourInCup();
            // isCustomerWantsCondiments() 是一个具体的方法
            if (isCustomerWantsCondiments()) {
                // 步骤 4 加入调味料
                addCondiments();
            }
    
        }
    
        /**
         * 基本方法,将水煮沸
         * 这是一个通用的,没有差别的方法,
         * 设置访问权限为私有,向下屏蔽细节
         */
        private void boilWater() {
            System.out.println("固定方法--将水煮沸");
        }
    
        /**
         * 基本方法,将饮料倒入杯中
         */
        private void pourInCup() {
            System.out.println("固定方法--将饮料倒入杯中");
        }
    
        /**
         * 须要在子类中可见,延迟到子类实现具体细节
         * 抽象的基本方法,泡制饮料
         */
        protected abstract void brew();
    
        /**
         * 加入调味料
         */
        protected abstract void addCondiments();
    
        /**
         * Hook,钩子函数,提供一个默认的或者空的实现
         * 具体子类可以自行决定是否挂钩,以及如何挂钩
         * 询问用户是否加入调料
         *
         * @return
         */
        protected boolean isCustomerWantsCondiments() {
            return true;
        }
    
    }
    

    编写两个实现类

    1、茶类(加调料)

    注意:须要重写加调料 isCustomerWantsCondiments() 方法。

    public class Tea extends RefreshBeverage {
        @Override
        protected void brew() {
            System.out.println("特殊方法--用 80 度的水冲泡茶叶");
        }
    
        @Override
        protected void addCondiments() {
            System.out.println("特殊方法--加入柠檬");
        }
    
        /**
         * 子类通过覆盖的形式选择挂载钩子函数,
         * 钩子函数让子类更加灵活
         * @return
         */
        @Override
        protected boolean isCustomerWantsCondiments(){
            return false;
        }
    }
    

    2、咖啡类(不加调料)

    不加调料是默认实现,所以无须覆盖 isCustomerWantsCondiments() 方法。

    public class Coffee extends RefreshBeverage {
        @Override
        protected void brew() {
            System.out.println("特殊方法--用沸水冲泡咖啡");
        }
    
        @Override
        protected void addCondiments() {
            System.out.println("特殊方法--加入糖和牛奶");
        }
    }
    

    编写测试方法:

    public class Main {
        
        public static void main(String[] args) {
            RefreshBeverage tea = new Tea();
            tea.prepareBeverageTemplate();
    
            System.out.println("------ 愉快的分割线 ------");
    
            RefreshBeverage coffee = new Coffee();
            coffee.prepareBeverageTemplate();
        }
    
    }
    

    运行结果:

  • 相关阅读:
    extjs 为组件动态添加插件
    springboot使用spring-cloud-starter-alibaba-sentinel导致响应变成xml格式
    js 将数据保存到本地
    iframe跨域安全
    nginx url自动301加斜杠
    EXTJS防止表单中回车触发提交
    servlet
    Struts1和Struts2的区别
    AWT和Swing的简记
    sleep()和wait()
  • 原文地址:https://www.cnblogs.com/liweiwei1419/p/6784476.html
Copyright © 2020-2023  润新知