美文网首页设计模式
模板方法模式

模板方法模式

作者: GeekerLou | 来源:发表于2020-03-08 09:58 被阅读0次

    模板方法模式

    含义概述

    模板方法模式在一个方法中定义一个算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

    使用场景

    当有一个业务有 N 个步骤( 模板 ),其中一部分步骤是永恒不变的,那么就将不变的这些步骤抽象到父类中,可能变化的步骤留给子类去实现。

    组成元素

    • 模板方法:定义算法的整体流程,通常推荐使用 final 关键字修饰,防止子类重写,从而破坏了模板中规定好的流程
    • 抽象方法:使用 abstract 修饰,让子类去实现
    • 普通方法:父类提供默认实现,设置为private则不允许子类也可重写,设置为public或者proteced则允许子类重写,具体访问修饰符的级别设置可以根据需求设定,不做强制规定
    • 钩子方法:模板方法中提前预埋多个钩子,让子类有一定的能力影响抽象类中的算法流程。

    案例

    1. Servlet 中的模板方法:doGet()/doPost()/service()方法
    2. Arrays.sort() 方法,它要求对象实现 Comparable 接口

    优缺点比较

    模板方法模式是将子类中不变的部分抽象到父类,可变的部分由子类去实现。

    1. 优点
      封装不变公共代码,便于维护。可变部分的代码由子类自由决定,扩展性强。

    2. 缺点
      每新增一个不同的实现都需要增加一个子类,可能导致类数量变多,增加系统复杂性。

    实例

    Cook.java

    public abstract class Cook {
    
        /**
         * 钩子的开关变量
         */
        protected boolean needBeforeCook = false;
    
        /**
         * 钩子的开关
         *
         * @return
         */
        protected boolean needBeforeCook() {
            System.out.println("===钩子函数被禁用===");
            return false;
        }
    
        /**
         * 钩子函数
         */
        public void beforeCook() {
        }
    
    
        public void open() {
            System.out.println("打开抽油烟机");
        }
    
        public void fire() {
            System.out.println("生火");
        }
    
        /**
         * 期望子类去实现
         */
        public abstract void doCook();
    
        public void outfire() {
            System.out.println("灭火");
        }
    
        public void close() {
            System.out.println("关闭抽油烟机");
            System.out.println("======收工=======");
        }
    
        /**
         * 使用final关键字,防止子类重写
         */
        public final void cook() {
            // 默认开启钩子函数
            if (this.needBeforeCook()) {
                this.beforeCook();
            }
    
            this.open();
            this.fire();
            this.doCook();
            this.outfire();
            this.close();
        }
    }
    

    CookMeat.java

    /**
     * 炒肉
     */
    public class CookMeat extends Cook {
    
        @Override
        public boolean needBeforeCook() {
            return true;
        }
    
        @Override
        public void beforeCook() {
            System.out.println("腌制");
        }
    
        @Override
        public void doCook() {
            System.out.println("红烧肉");
        }
    }
    

    CookVegatables.java

    public class CookVegatables extends Cook {
    
    
        @Override
        public void doCook() {
            System.out.println("炒蔬菜");
        }
    }
    

    单元测试

    import com.netease.learn.designPattern.templateMethod.Cook;
    import com.netease.learn.designPattern.templateMethod.CookMeat;
    import com.netease.learn.designPattern.templateMethod.CookVegatables;
    import org.junit.Test;
    
    public class TemplateMethodTest {
    
        @Test
        public void test1() {
            Cook cook = new CookMeat();
            cook.cook();
        }
    
        @Test
        public void test2() {
            Cook cook = new CookVegatables();
            cook.cook();
        }
    }
    

    参考资料

    1. 代码仓库-模板方法模式

    相关文章

      网友评论

        本文标题:模板方法模式

        本文链接:https://www.haomeiwen.com/subject/dnzrdhtx.html