zoukankan      html  css  js  c++  java
  • 设计模式:模版模式(Template Pattern)-转

    模版模式

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

     

    我们使用冲泡咖啡和冲泡茶的例子

    加工流程:

    咖啡冲泡法:1.把水煮沸、2.用沸水冲泡咖啡、3.把咖啡倒进杯子、4.加糖和牛奶

    茶冲泡法:   1.把水煮沸、2.用沸水冲泡茶叶、3.把  茶 倒进杯子、4.加蜂蜜

    一、创建一个创模板(抽象)类

    package com.kaishengit.beverage;
    
    public abstract class Beverage {
        /**
         * 冲泡咖啡或茶...流程
         */
        public final void create(){
            boilWater();//把水煮沸
            brew();//用沸水冲泡...
            pourInCup();//把...倒进杯子
            addCoundiments();//加...
        }
    
    
        public abstract void addCoundiments();
    
        public abstract void brew();
        
        public void boilWater() {
            System.out.println("煮开水");
        }
        
        public void pourInCup() {
            System.out.println("倒进杯子");
        }
    }

    2>创建一个咖啡类(Coffee)和茶(Tea)类,都继承Beverage抽象类

    1.咖啡(Coffee)

    package com.kaishengit.beverage;
    
    public class Coffee extends Beverage{
    
        @Override
        public void addCoundiments() {
            System.out.println("添加糖和牛奶");    }
    
        @Override
        public void brew() {
            System.out.println("用水冲咖啡");
        }
    }

    2.茶(Tea)

    package com.kaishengit.beverage;
    
    public class Tea extends Beverage{
    
        @Override
        public void addCoundiments() {
            System.out.println("添加蜂蜜");
        }
    
        @Override
        public void brew() {
            System.out.println("用水冲茶");
        }
    
    }

    3.我们测试一下:

    package com.kaishengit.beverage;
    
    public class Test {
        public static void main(String[] args) {
            Coffee coffee = new Coffee();
            coffee.create();//冲泡咖啡
            
            //Tea tea = new Tea();//冲泡茶
            //tea.create();
        }
    }

     运行结果:

    -----------------------------------

    煮开水

    用水冲咖啡

    倒进杯子

    添加糖和牛奶

    -----------------------------------

    在模版模式中使用挂钩(hook)

    存在一个空实现的方法,我们称这种方法为”hook”。子类可以视情况来决定是否要覆盖它。

     

    1>我们对模板类(Beverage)进行修改

    package com.kaishengit.beverage;
    
    public abstract class Beverage {
        /**
         * 冲泡咖啡或茶...流程
         */
        public final void create(){
            boilWater();//把水煮沸
            brew();//用沸水冲泡...
            pourInCup();//把...倒进杯子
            addCoundiments();//加...
            
            hook();//挂钩
        }
        //空实现方法
        public void hook(){}
    
        public abstract void addCoundiments();
    
        public abstract void brew();
        
        public void boilWater() {
            System.out.println("煮开水");
        }
        
        public void pourInCup() {
            System.out.println("倒进杯子");
        }
    }

    2>假如我们搞活动,喝一杯咖啡送一杯,修改咖啡(Coffee)类

    package com.kaishengit.beverage;
    
    public class Coffee extends Beverage{
    
        @Override
        public void addCoundiments() {
            System.out.println("添加糖和牛奶");    }
    
        @Override
        public void brew() {
            System.out.println("用水冲咖啡");
        }
        
        /**
         * 挂钩
         */
        @Override
        public void hook() {
            System.out.println("再来一杯");
        }
    
    }

    3>使用上面的测试类

    运行结果:

    --------------------------------

     

    煮开水

    用水冲咖啡

    倒进杯子

    添加糖和牛奶

    再来一杯

    --------------------------------

    结果中有“再来一杯”...

    我们也可以这样使用挂钩,让其决定里面的代码是否执行

    1>我们对模板类(Beverage)进行修改

    package com.kaishengit.beverage;
    
    public abstract class Beverage {
        /**
         * 冲泡咖啡或茶...流程
         */
        public final void create(){
            boilWater();//把水煮沸
            brew();//用沸水冲泡...
            pourInCup();//把...倒进杯子
            
            //挂钩决定是否添加配料
            if(hook()){
                addCoundiments();//加...
            }
            //hook();
        }
    
        /**
         * 默认添加配料
         * @return
         */
        public boolean hook() {
            return true;
        }
    
        //public void hook(){}
        
        public abstract void addCoundiments();
    
        public abstract void brew();
        
        public void boilWater() {
            System.out.println("煮开水");
        }
        
        public void pourInCup() {
            System.out.println("倒进杯子");
        }
    }

    2>我们对Coffee类进行修改,让其不添加配料

    package com.kaishengit.beverage;
    
    public class Coffee extends Beverage{
    
        @Override
        public void addCoundiments() {
            System.out.println("添加糖和牛奶");    }
    
        @Override
        public void brew() {
            System.out.println("用水冲咖啡");
        }
        
        /**
         * 有的客人不喜欢加配料
         */
        @Override
        public boolean hook() {
            return false;
        }
        
        /*@Override
        public void hook() {
            System.out.println("再来一杯");
        }
    */
    }

     3>还是使用上面的测试类

    运行结果:

    ------------------------------------------------------

     

    煮开水

    用水冲咖啡

    倒进杯子

    ------------------------------------------------------

    运行结果中没有添加配料

    关于模板模式

     

    1>模板模式定义了算法的步骤,把这些步骤的实现延迟到子类

    2>模板模式为我们提供了一个代码复用的技巧

    3>模板抽象类中可以定义具体方法、抽象方法和钩子方法

    4>为了防止子类改变模板中的算法,可以将模板方法声明为final

    5>钩子是一种方法,它在抽象类中不做事,或只做默认的事,子类可以选择要不要实现它

  • 相关阅读:
    operator模块和functools模块
    函数注解
    用户定义的可调用类型、从定位参数到仅限关键字参数
    可调用对象
    nxos启动的初始化和https访问nx-api
    网络安全基础之网络协议与安全威胁
    华为AC中服务集命令解释配置
    转:图解ARP协议(四)代理ARP原理与实践(“善意的欺骗”)
    windows下python3 python2 共存下安装virtualenvwrapper
    关于网络安全学习的网站
  • 原文地址:https://www.cnblogs.com/liunanjava/p/4802820.html
Copyright © 2011-2022 走看看