• Head First设计模式(阅读笔记)-09.模板方法模式


    咖啡和茶的冲泡

    假设咖啡的冲泡过程为把水煮沸--》用沸水泡咖啡--》把咖啡倒入杯子--》加糖和奶,而茶的冲泡过程为把水煮沸--》用沸水泡茶叶--》把茶倒入杯子--》加柠檬。在现有实现的基础上,如何体现更好的封装性?


    public class Coffee{
        // 咖啡冲泡过程
        void prepareRecipe(){
            boilwater();
            brewCoffeeGrinds();
            pourInCup();
            addSugarAndMilk();
        }
    	// 上述方法的具体实现
    }
    
    public class Tea{
        // 茶冲泡过程
        void prepareRecipe(){
            boilwater();
            steepTeaBag();
            pourInCup();
            addLemon();
        }
    	// 上述方法的具体实现
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    模板方法模式

    • 定义了一个算法的步骤,并将一些实现步骤延迟到子类中(即让子类提供某些步骤的实现)
    • 工厂方法是模板方法的特殊版本

    模式表述
    模板方法子类决定如何实现算法中的某些步骤
    策略封装可交换的行为,然后使用委托决定要采用哪一个行为
    工厂方法哪个具体类
    提取相似点

    在两者制作过程中,boilWater方法和pourInCup方法都是一样的,可以抽象放到基类中


    public abstract class CaffeinBeverage{  // 基类
        // 其余代码后续说明
        void boilWater(){...}
    	void pourInCup(){...}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    抽象prepareRecipe方法

    除了上述两个一样的方法,还存在相似点:brewCoffeeGrindsteepTeaBag以及addSugarAndMilkaddLemon是两对差异不大的方法,可以将第一组抽象为brew方法,第二组抽象为addCondiments方法,同样放到基类中


    public abstract class CaffeinBeverage{
        // 声明为final是因为不希望子类去重写该方法
        final void prepareRecipe(){
            boilWater();
            brew();
            pourInCup();
            addCondiments();
        }
        // 声明为抽象,让子类去实现
        abstract void brew();
        abstract void addCondiments();
        
        void boilWater(){...}
    	void pourInCup(){...}
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    开始冲泡

    以冲泡茶为例


    public class Tea extends CaffeinBeverage{
        public void brew(){
            System.out.println("Steeping the tea");
        }
        public void addCondiments(){
            System.out.println("Adding Lemon");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    对模板方法进行挂钩
    • 钩子是一种被声明在抽象类中的方法,它具有空或默认实现
    • 钩子是为了让子类有能力对算法的不同点进行挂钩(由子类决定要不要挂钩)

    public abstract class CaffeinBeverageWithHook{
        final void prepareRecipe(){
            boilWater();
            brew();
            pourInCup();
            if(customerWantsCondiments){
            	addCondiments();
    		}
        }
        // 钩子,子类可以选择覆盖
        boolean customerWantsCondiments(){
    		return true;
        }
        // 其余代码一致
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    排序鸭子


    模板方法排序

    Java Arrays类中提供了模板方法进行排序,其中Sort是模板方法,并且**CompareTo延迟到子类去实现**


    // 之所以定义为static是因为数组无法继承,也就无法通过xxx.sort使用排序,而是Arrays.sort(xxx)
    public static void sort(Object[] a){
        Object[] aux = (Object[])a.clone();
        merge(aux, a, 0, a.length, 0);
    }
    private static void merge(Object[] src, Object[] dest, int low, int high, int off){
        for(int j = i; j > low && ((Comparable)dest[j - 1]).compareTo((Comparable)dest[j]) > 0; j--){
            swap(dest, j, j-1);  // 在Arrays类中定义了
        }
        return;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    鸭子类

    public class Duck implements Comparable{  // 实现Comparable接口中的compareTo方法,
        int weight;
        public int compareTo(Object o){
            Duck otherDuck = (Duck)o;
            if(this.weight < otherDuck.weight){
                return -1;
            }else if(this.weight == otherDuck.weight){
                return 0;
            }else{
                return 1;
            }
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    参考

    Head First 设计模式-模板方法模式

    设计模式-模板模式

  • 相关阅读:
    [论文笔记]Poly-encoder
    leecode337. 打家劫舍 III
    Linux命令(101)之nl
    C++ Qt如何往Windows AppData目录写数据
    网络信息安全与防范研究
    hive元数据的mysql迁移和升级的流程方案
    《如何使用C语言去下三子棋?》
    通过sonic-ci-helper插件与Sonic平台结合实现多设备批量安装应用
    docker 容器如何使用tini 作为启动进程并 清理、管理 Docker 容器僵死进程
    淘宝/天猫、1688API-按关键字搜索商品item_search
  • 原文地址:https://blog.csdn.net/qq_41398418/article/details/128169652