深入浅出设计模式之模板方法模式

来源:互联网 发布:高校大数据实验室 编辑:程序博客网 时间:2024/05/19 22:55

引子

我们发现茶喝咖啡有相似的地方,当然,泡茶喝和泡咖啡也有相似的地方。

咖啡和茶的类://咖啡类public class Coffee {    //准备咖啡    void prepare(){        //加入咖啡        addCoffee();        //加入水        boilWater();        //加牛奶        addMilk();    }    private void addCoffee(){        System.out.println("add coffee!");    }    private void boilWater(){        System.out.println("boil water!");    }    private void addMilk(){        System.out.println("boil milk!");    }}//茶类public class Tea {    //准备茶    void prepare(){        addTea();        boilWater();        addLemon();    }    private void addTea(){        System.out.println("add tea!");    }    private void boilWater(){        System.out.println("boil water!");    }    private void addLemon(){        System.out.println("boil lemon!");    }}

出现重复的代码,两个类都有倒入水方法,我们需要把这些重复代码抽取出来

第一版的实现

public abstract class Beverage {    //因为prepare在两个类中不一样,所以只能作为抽象方法    abstract void prepare();    //两个类中都一样,可以提取出来    private void boilWater(){        System.out.println("boil water!");    }}

但是我们抽象的不够彻底,另外两个方法虽然不一样,但是方法相似。

比如咖啡的addCoffee 与茶的addTea,咖啡的addMilk 与茶的addLemon,虽然动作不一样,方式行为方式一样,我们可以用一个方法来代替相似的行为。

public abstract class Beverage {    // 因为prepare在两个类中不一样,所以只能作为抽象方法    void prepare() {        //冲泡        brew();        // 加入水        boilWater();        // 加配料        addBurden();    }    //抽象方法由子类实现    abstract void brew();    abstract void addBurden();    // 两个类中都一样,可以提取出来    private void boilWater() {        System.out.println("boil water!");    }}

只要子类实现两个抽象的方法就行了。

定义

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

其实我们对这些代码一点都不陌生,因为模板方法可以说是最常用的方法之一。

public abstract class Beverage {    // 因为prepare在两个类中不一样,所以只能作为抽象方法    final void prepare() {        //冲泡        brew();        // 加入水        boilWater();        // 加配料        addBurden();    }    //抽象方法由子类实现    abstract void brew();    abstract void addBurden();    // 两个类中都一样,可以提取出来    final void boilWater() {        System.out.println("boil water!");    }    //钩子函数    void hook(){}}

我们一般发由子类实现的函数用abstract修饰,已实现的方法final防止子类修改,也可以加入一个普通的钩子函数,子类可以实现,也可以不实现

在Swing中的JFame里的paint就是一个钩子函数,当子类实现paint时,就会运行paint里的函数。

0 0
原创粉丝点击