您的位置:首页 > 编程语言 > Java开发

设计模式 - 模板方法模式

2017-12-03 00:00 267 查看
去银行办业务,我们可以总结为取号、等号、办业务,区号和等号每个人没什么不同;但业务就有不同,有人存款,有人取款。

对于这种一套业务流程中,各个模块大同小异的情况,定义出业务流程的基本框架,而将一些步骤延迟到子类中,称为模板方法模式。

意图

定义一个操作中的算法的骨架,而将一些步骤延迟到子类中。模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。

示例

该模式比较简单,直接在代码中进行部分说明

假设泡咖啡和沏茶的步骤可以抽象为如下:

将水煮沸

泡制饮料(咖啡:沸水冲泡 茶:温水浸泡)

将饮料倒入杯中

加入调味料(咖啡:加入牛奶和糖 茶: 加入柠檬)

抽象骨架示例

package com.dotleo.template;

/**
* 饮料制作模拟
*
* 抽象基类,为所有子类提供一个算法框架
*
* 思想:
* 子类可以改变父类中可变的逻辑结构,但不能改变整体结构
*
* 步骤:
* 定义模板方法,模板方法使用非private修饰,最好用public修饰,保证子类可以在任何地方使用;使用final修饰,避免了子类的复写
* 将统一的方法实现,并用private修饰,避免子类复写;将不统一的方法定义为抽象方法,并用非private修饰,子类复写可以实现不同的功能
*
* @author LiuFei
* @create 2017-12-03 17:20
*/
public abstract class RefreshBeverage {

/**
* 纸杯饮料的模板方法
* 封装了所有子类共同遵循的算法框架
*/
public final void prepareBeverageTemplate() {
// 1. 将水煮沸
boilWater();
// 2. 泡制饮料
brew();
// 3. 将饮料倒入杯中
pourInCup();
// 4. 加入调味料
addCondiments();
}

/**
* 将水煮沸(统一方法,实现)
*/
private void boilWater() {
System.out.println("将水煮沸");
}

/**
* 泡制饮料(不统一方法,抽象)
*/
protected abstract void brew();

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

/**
* 加入调味料(不统一方法,抽象)
*/
protected abstract void addCondiments();

}

模拟制作咖啡

package com.dotleo.template;

/**
* 模拟制作咖啡
*
* @author LiuFei
* @create 2017-12-03 17:42
*/
public class Coffee extends RefreshBeverage {
@Override
protected void brew() {
System.out.println("用沸水冲泡咖啡");
}

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

模拟制作柠檬茶

package com.dotleo.template;

/**
* 模拟制作柠檬茶
*
* @author LiuFei
* @create 2017-12-03 17:48
*/
public class Tea extends RefreshBeverage {
@Override
protected void brew() {
System.out.println("用温水浸泡茶叶5分钟");
}

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

测试类

package com.dotleo.template;

/**
* @author LiuFei
* @create 2017-12-03 17:45
*/
public class RefreshBeverageTest {

public static void main(String[] args) {

// 制备咖啡
System.out.println("制备咖啡...");
RefreshBeverage coffeeRefreshBeverage = new Coffee();
coffeeRefreshBeverage.prepareBeverageTemplate();
System.out.println("咖啡好了!");

System.out.println("\n======================================================\n");

// 制备柠檬茶
System.out.println("制备柠檬茶...");
RefreshBeverage teaRefreshBeverage = new Tea();
teaRefreshBeverage.prepareBeverageTemplate();
System.out.println("柠檬茶好了!");
}
}

测试结果



优缺点

优点:

封装不变部分,扩展可变部分。

提取公共代码,便于维护。

行为由父类控制,子类实现。

缺点:

每一个不同的实现都需要一个子类来实现,导致类的个数增加,使得系统更加庞大。

使用场景

有多个子类共有的方法,且逻辑相同。

重要的、复杂的方法,可以考虑作为模板方法。

注意事项

为防止恶意操作,一般模板方法都加上
final
关键词。

如果骨架中有不想让子类重写的方法,可以使用
private
修饰
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息