zoukankan      html  css  js  c++  java
  • 模板方法模式

    一、简介

    模板方法模式是类的行为模式,需要开发抽象类和具体子类的工程师之间的合作。一个工程师负责给出一个算法的轮廓和骨架,另一个工程师负责给出这个算法的各个逻辑步骤。代表这些具体逻辑步骤的方法称为基本方法,而将这些基本方法汇总起来的方法叫做模板方法。

    二、设计思想

    模板模式通常会设计一个抽象类,内部定义一些需要子类去实现的方法;抽象类中还应该有一个或多个模板方法,即固定好的框架,而且这个方法被定义为final,不允许子类去修改。在这个固定的模板方法内部,会调用那些抽象方法,来一步步实现整个算法流程。通常子类都要去继承这个抽象父类,去实现属于自己的业务逻辑。

    三、程序示例背景

    先要手工制作饮料,比如我们办公室常见的泡咖啡和泡茶,制作的流程可以分为:煮水、准备原料、冲水、加入调料;其中第一、三步的动作是一样的。所以这两个动作可以在父类中直接实现,而第二、四步,对于泡咖啡和泡茶来说则有区别,因此可以设计成抽象方法,在各自的子类中实现。而这四个动作又是制作饮料的固定流程,可以定义成模板方法,并用final来修饰。

    抽象类:

    复制代码
    /**
     * 模板模式
     * 抽象类
     * @author  Administrator
     * @version  [版本号, 2016-10-21]
     */
    public abstract class MakeBeverage
    {
        /** 
         * 模板方法
         */
        public final void prepareBeverage()
        {
            boilWater();
            brew();
            pourInCup();
            addCondiments();
        }
        
        private void boilWater()
        {
            System.out.println("将水煮沸");
        }
        
        protected abstract void brew();
        
        private void pourInCup()
        {
            System.out.println("将水倒入杯中");
        }
        
        protected abstract void addCondiments();
    }
    复制代码

    子类实现:

    复制代码
    /**
     * 泡茶
     */
    public class TeaBeverage extends MakeBeverage
    {
    
        @Override
        protected void brew()
        {
            System.out.println("烘焙茶叶");
        }
    
        @Override
        protected void addCondiments()
        {
            System.out.println("加入茶叶调料");
        }
        
    }
    复制代码
    复制代码
    /**
     * 泡咖啡
     */
    public class CoffeeBeverage extends MakeBeverage
    {
        @Override
        protected void brew()
        {
            System.out.println("烘焙咖啡豆");
        }
    
        @Override
        protected void addCondiments()
        {
            System.out.println("加入咖啡调料");
        }
        
    }
    复制代码

    这样我们可以按照不同人的需要分别制作茶和咖啡这两款饮料。我们再想想,茶分很多种,如果有人要喝不加调料的差,我们的程序该怎么办?

    这时候模板模式提供了一个钩子方法,用于在模板方法中定制某些动作。

    我们将上面的抽象类做些改动:

    复制代码
    /**
     * 模板模式
     * 抽象类
     * @author  Administrator
     * @version  [版本号, 2016-10-21]
     */
    public abstract class MakeBeverage
    {
        /** 
         * 模板方法
         */
        public final void prepareBeverage()
        {
            boilWater();
            brew();
            pourInCup();
            //钩子方法,从需求方出发,可以选择是否需要这一个动作
            if(hookMethod())
            {
                addCondiments();
            }
        }
        
        private void boilWater()
        {
            System.out.println("将水煮沸");
        }
        
        protected abstract void brew();
        
        private void pourInCup()
        {
            System.out.println("将水倒入杯中");
        }
        
        protected abstract void addCondiments();
        
        //钩子方法
        protected boolean hookMethod()
        {
            //默认值,可以让子类去重写
            return true;
        }
    }
    复制代码

    我们来看下子类是如何实现的,由于不添加调料的茶也是属于茶的一类。我们让它去实现类TeaBeverage:

    复制代码
    /**
     * 不添加调料的茶
     */
    public class ChineseTeaBeverage extends TeaBeverage
    {
        @Override
        protected boolean hookMethod()
        {
            return false;
        }
    }
    复制代码

    四、使用场景

    模板模式用于那种几个动作组合的场景,将其中可变的部分留给子类去实现,而将子类公共部分的代码提炼到父类中去实现,防止代码重复。至于钩子函数,只允许在特定点上调用,这样就可以控制在特定点进行扩展。

      

  • 相关阅读:
    Silverlight应用小知识点
    svn如何给新文件加锁
    sql统计上周销售量的起止时间
    sql中null 和 ‘’(空字符串)
    蓝桥杯 算法训练 操作格子 [ 线段树 ]
    90分 蓝桥杯 算法提高 道路和航路 [ 最短路 ]
    蓝桥杯 算法训练 安慰奶牛 [ 最小生成树 ]
    蓝桥杯 算法提高 金属采集 [ 树形dp 经典 ]
    转 蓝桥杯 历届试题 大臣的旅费 [ dfs 树的直径 ]
    蓝桥杯 算法训练 最短路 [ 最短路 bellman ]
  • 原文地址:https://www.cnblogs.com/csguo/p/7589116.html
Copyright © 2011-2022 走看看