设计模式-模板模式

目录

 

1、引入

2、使用模板模式

重点描述模板模式的类图

对hook的理解


1、引入

喝茶与泡咖啡过程:

准备喝咖啡时,我们的步骤是

1.把水煮沸

2.用沸水冲泡咖啡

3.倒进杯子

4.加糖和牛奶

准备喝茶的时,步骤是

1.把水煮沸

2.用沸水浸泡茶叶

3.倒进杯子

4.加柠檬

public class Coffee {

    void prepareRecipe(){
        boilWater();
        brewCoffeeGrinds();
        pourInCup();
        addSugarAndMilk();
    }

    public void boilWater(){
        System.out.println("boiling water...");
    }

    public void brewCoffeeGrinds(){
        System.out.println("dripping coffee through filter");
    }

    public void pourInCup(){
        System.out.println("pouring into cup");
    }

    public void addSugarAndMilk(){
        System.out.println("adding sugar and milk");
    }
}

public class Tea {

    void prepareRecipe(){
        boilWater();
        steepTeaBag();
        pourInCup();
        addLemon();
    }

    public void boilWater(){
        System.out.println("boiling water...");
    }

    public void steepTeaBag(){
        System.out.println("steeping the tea...");
    }

    public void addLemon(){
        System.out.println("adding lemon...");
    }

    public void pourInCup(){
        System.out.println("Pouring into cup...");
    }
}

可以发现,其实泡茶和泡咖啡的过程就是一个固定骨架步骤的“算法”,我们可以抽象为:

  1. 煮沸水
  2. 冲泡
  3. 将泡好的饮料倒入杯子
  4. 根据需求加入调料

标蓝部分为算法中不一样的部分,如何解决?下面,我们用“模板方法模式”来解决这种不一致。

2、使用模板模式

模板方式:定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现,模板方法使得子类可以在不改变算法结构的情况下,重新定义算法中的某些步骤

//模板
public abstract class HotDrink {

    //步骤是固定的,所以使用final修饰过程
    final void prepareRecipe(){
        boilWater();
        brew();
        pourInCup();
        addCondiments();
    }

    void boilWater() {
        System.out.println("boiing water...");
    }

    //不一样的部分做成抽象类,等待子类去实现
    abstract void brew();

    abstract void addCondiments();

    void pourInCup(){
        System.out.println("pouring into cup...");
    }

}

此时后面的coffee和tea,只需实例化各自特殊的部分,整个烘焙的过程,还是使用模板进行操作(并且已经使用final写死)

//继承模板,然后将操作进行实例化
public class Coffee extends HotDrink{

    @Override
    void brew() {
        System.out.println("driping coffee through filter...");
    }

    @Override
    void addCondiments() {
        System.out.println("adding sugar and milk");
    }

}

 
public class Tea extends HotDrink {
 
	void brew() {
		System.out.println("Steeping the tea");
	}
 
	void addCondiments() {
		System.out.println("Adding Lemon");
	}
 
}

模板方法将算法定义成一组步骤,其中的任何步骤都可以是抽象的,由子类负责实现。这样可以确保算法的结构保持不变,同时由子类提供部分的实现

所以,模板方法就是定义了一个算法的步骤,并允许子类为一个或多个步骤提供实现

重点描述模板模式的类图

1、templateMethod:

模板方法,就是此处的烘焙过程。

2、AbsOperation:

抽象方法,需要子类自己去实现特殊功能。(例如此处的加调料)

3、concreteOp:

具体方法,由模板进行操作,统一的行为。(例如此处的少水)

4、hook

可选的操作,由模板超类进行实现,允许子类进行重写实现特殊功能。(就是有些特殊功能,超类已经实现,子类自行决定是否重写)

对hook的理解

hook允许子类重载步骤,可以确保不同需求步骤的算法的实现。

钩子是一种被声明在抽象类中的方法,但只有空的或者默认的实现。钩子的存在,可以让子类有能力对算法的不同点进行挂钩。要不要挂钩,由子类自行决定。

简单点说,钩子就是对算法中步骤的不同(省略或增加)而设计的。在上面的代码中,我们写了一个钩子来决定是否加调料

    /**
     * “钩子”方法。顾客决定是否加调料
     */
    public Boolean customerWantsCondiment(){
        return true;
    }
    /**
     * 模板方法,准备饮料
     */
    public final void prepareRecipe(){
        boilWater();
        brew();
        //用于模板方法的算法中可选部分的控制
        if(customerWantsCondiment())
            addCondiment();
        pourInCup();
    }
public class Tea extends CaffeineBeverage{

    @Override
    public void brew() {
        System.out.println("浸泡茶叶");
    }

    @Override
    public void addCondiment() {
        System.out.println("添加蜂蜜");
    }

    //覆盖父类的“钩子”方法,更改算法中的可选部分
    @Override
    public Boolean customerWantsCondiment(){
        //询问顾客是否需要调料
        String answer = askCustomerNeedCondiment();
        if("y".equals(answer))
            return true;
        else
            return false;
    }

    private String askCustomerNeedCondiment() {
        String answer = null;

        System.out.println("请问您要不要加蜂蜜?请回答y或n");
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        try {
            answer = in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return answer;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值