模板方法模式学习笔记

模板方法的实现要素:抽象基类和具体子类

抽象基类:(1)基本方法:共有的方法,用private修饰

     (2)抽象方法:只知道原则,不知道具体实现,要延迟到子类中实现,用protected abstract修饰

       (3)可选的钩子:具体的子类可以自行决定是否挂钩以及如何挂钩,从而影响算法的实现,用protected修饰

       (4)Template方法:封装了所有子类共同遵循的算法框架,用final修饰,不让子类覆盖重写。

                 模板方法定义成final,即表示子类可以替换掉父类中的可变逻辑,但不能改变掉整体逻辑结构。(好莱坞原则)

具体子类:(1)实现基类中的抽象方法

       (2)可选的覆盖钩子方法,来更加个性化来影响算法的局部行为。

 

总结:

准备一个抽象类,将部分逻辑以具体方法的形式实现,然后声明一些抽象方法交由子类实现剩余逻辑,用钩子方法给予子类更大的灵活性。最后将方法汇总构成一个不可改变的模板方法。

 

模板方法模式的适用场景:

(1)算法或操作遵循相似的逻辑

(2)重构时(把相同的代码抽取到父类中)

(3)重要,复杂的算法,核心算法设计为模板算法

 

模板方法模式的优点:

(1)封装性好

(2)复用性好

(3)屏蔽细节

(4)便于维护

 

模板方法模式的缺点:

(1)继承(Java语言只支持单继承),但我们重构一个系统时,假如有些类已经继承了相关父类,那就无法再继承模板方法的抽象基类。

 

简单代码示例如下:

/**
* 抽象基类,为所有子类提供一个算法框架
*
* 提神饮料
*
* @author zhx
*
*/
public abstract class RefreshBeverage {

/*
* 制备饮料的模版方法 封装了所有子类共同遵循的算法框架
*/
public final void prepareBeverageTemplate() {
// 步骤1:将水煮沸
boilWater();
// 步骤2:泡制饮料
brew();
// 步骤3:将饮料倒入杯中
pourInCup();

if(isCustomerWantsCondiments()) {
// 步骤4:加入调味料
addCondiments();
}

}

/*
* Hook,钩子函数,提供一个默认或空的实现
* 具体的子类可以自行决定是否挂钩以及如何挂钩
* 询问用户是否加入调料
*/
protected boolean isCustomerWantsCondiments() {
return true;
}

/*
* 基本方法,将水煮沸
*/
private void boilWater() {
System.out.println("将水煮沸");
}

/*
* 抽象的基本方法,泡制饮料
*/
protected abstract void brew();

/*
* 基本方法,将饮料倒入杯中
*/
private void pourInCup() {
System.out.println("将饮料倒入杯中");
}

/*
* 抽象的基本方法:加入调味料
*/
protected abstract void addCondiments();

}

 

/**
* 具体子类,提供了制备咖啡的具体实现
* @author zhx
*
*/
public class Coffee extends RefreshBeverage {

@Override
protected void brew() {
System.out.println("用沸水冲泡咖啡");
}

@Override
protected void addCondiments() {
System.out.println("加入糖和牛奶");
}

}

 

/**
* 具体子类:提供了制备茶的具体实现
* @author zhx
*
*/
public class Tea extends RefreshBeverage{

@Override
protected void brew() {
System.out.println("用80℃的热水浸泡茶叶5分钟");
}

@Override
protected void addCondiments() {
System.out.println("加入柠檬");
}

/*
* 子类通过覆盖的形式选择挂载钩子函数
* @see edu.bnuz.zhx.design_pattern.template.RefreshBeverage#isCustomerWantsCondiments()
*/
@Override
protected boolean isCustomerWantsCondiments() {
return false;
}

}

 

public class RefreshBeverageTest {

public static void main(String[] args) {

System.out.println("制备咖啡中...");
RefreshBeverage coffee = new Coffee();
coffee.prepareBeverageTemplate();
System.out.println("咖啡制备完成...");

System.out.println("-----------------------------------");
System.out.println("制备茶中...");
RefreshBeverage tea = new Tea();
tea.prepareBeverageTemplate();
System.out.println("茶制备完成...");
}

}

posted @ 2015-06-10 10:00  丶小八戒  阅读(155)  评论(0编辑  收藏  举报