2019-10-06 14:46阅读: 173评论: 0推荐: 0

【设计模式】模板方法

一、前言

  最近复习发现AQS使用了模板方法,自定义同步器时需要重写几个AQS提供的模板方法,Spring的DefaultBeanDefinitionDocumentReader#doRegisterBeanDefinitions() 方法也使用了该设计模式,于是写篇文章加深理解。

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

单看这句话可能还没搞懂这个设计模式是干嘛的,下面看一个例子。

二、示例

不用设计模式,冲咖啡和泡茶的两个类分别是下面这样的。

public class Coffee {
// 冲泡咖啡的算法
void prepareRecipe(){
boilWater();
// 用沸水冲泡咖啡
brewCoffeeGrinds();
pourInCup();
// 加牛奶和糖
addSugarAndMilk();
}
private void addSugarAndMilk() {
}
private void pourInCup() {
}
private void brewCoffeeGrinds() {
}
private void boilWater() {
}
}
public class Tea {
// 泡茶的算法
void prepareRecipe(){
boilWater();
// 用沸水浸泡茶叶
steepTeaBag();
pourInCup();
// 加柠檬
addLemon();
}
private void addLemon() {
}
private void pourInCup() {
}
private void steepTeaBag() {
}
private void boilWater() {
}
}

很容易就可以发现这两个类中有重复代码,boilWater()和pourInCup()都重复了可以提取出来,因为茶和饮料都是咖啡饮料可以定义一个超类CaffeineBeverage。
进一步分析,两种冲泡法其实都用了相同的算法:

  1. 把水煮沸
  2. 用热水泡咖啡或茶
  3. 把饮料倒进杯子
  4. 在饮料里加调料

所以prepareRecipe()也可以抽象成一个,如下:

final void prepareRecipe(){
boilWater();
// 交给对应的子类实现
brew();
pourInCup();
// 交给对应的子类实现
addCondiments();
}

最后,重构后的代码如下。

咖啡因饮料超类

public abstract class CaffeineBeverage {
/**
* 模板方法
* 定义的算法步骤
*/
final void prepareRecipe(){
boilWater();
brew();
pourInCup();
addCondiments();
}
/**
* 添加调料
*/
protected abstract void addCondiments();
/**
* 冲泡
*/
protected abstract void brew();
/**
* 煮开水
*/
private void boilWater() {
System.out.println("Boiling water");
}
/**
* 把饮料倒进杯子
*/
private void pourInCup() {
System.out.println("Pouring in cup");
}
}

Tea

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

Coffee

public class Coffee extends CaffeineBeverage {
@Override
protected void addCondiments() {
System.out.println("Adding Sugar and Milk ");
}
@Override
protected void brew() {
System.out.println("Dripping Coffee through filter");
}
}

代码的类图就变成了下面的样子。

 

类图
类图

 

道理我懂,可是使用了模板方法模式之后有什么好处吗?

原本的实现模板方法后的实现
Coffee和Tea之间存在重复代码 CaffeineBeverage类实现了代码复用最大化
Coffee和Tea控制了算法 由CaffeineBeverage类主导一切,拥有并保护算法
对算法所做的代码改变,需要修改子类很多地方 算法只存在一个地方,很容易修改
算法的知识和它的实现分散在许多类中 CaffeineBeverage类专注算法本身,而由子类提供完整的实现

三、总结

设计模式这么多种,要做到灵活运用还真是长路漫漫啊。

本文作者:烟味i

本文链接:https://www.cnblogs.com/2YSP/p/11627282.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   烟味i  阅读(173)  评论(0编辑  收藏  举报
历史上的今天:
2018-10-06 SpringBoot使用sharding-jdbc分库分表
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起