一、模板模式
模板模式封装了一个算法步骤,并允许子类为一个或多个步骤方法提供实现。模板模式可以使子类在不改变算法结构的情况下,重新定义算法中的某些步骤。
二、示例
泡咖啡与泡茶:
- 泡咖啡的步骤:
- 水烧开
- 冲泡咖啡粉
- 把咖啡倒入杯子
- 加糖和牛奶
- 泡茶步骤:
- 水烧开
- 冲泡茶叶
- 把茶水倒入杯子
- 加柠檬
面向对象模式的示例:
1.定义泡咖啡的方法类
/**
* 面向对象方法对象,泡咖啡,按固定流程走完
*/
public class Coffee {
/**
* 泡咖啡
*/
public void prepareRecipe() {
boilWater();
brewCoffee();
pourInCup();
addSugarMilk();
}
/**
* 煮开水
*/
public void boilWater() {
System.out.println("Boiling water");
}
/**
* 放咖啡粉
*/
public void brewCoffee() {
System.out.println("Brewing coffee");
}
/**
* 放进杯子里
*/
public void pourInCup() {
System.out.println("Pouring into cup");
}
/**
* 添加糖和奶
*/
public void addSugarMilk() {
System.out.println("Adding sugar or milk");
}
}
2.定义泡茶的方法类
/**
* 面向对象,泡茶,按固定流程走完
*/
public class Tea {
/**
* 泡茶
*/
public void prepareRecipe() {
boilWater();
brewTea();
pourInCup();
addLemon();
}
/**
* 煮开水
*/
public void boilWater() {
System.out.println("Boiling water");
}
/**
* 放茶叶
*/
public void brewTea() {
System.out.println("Brewing tea");
}
/**
* 放进杯子里
*/
public void pourInCup() {
System.out.println("Pouring into cup");
}
/**
* 添加柠檬
*/
public void addLemon() {
System.out.println("Adding lemon");
}
}
3.调用方法
/**
* 面向对象模式,调用对象内提供的方法
*/
public class MainTest {
public static void main(String[] args) {
Coffee coffee = new Coffee();
Tea tea = new Tea();
coffee.prepareRecipe();
tea.prepareRecipe();
}
}
三、模板模式
-
泡咖啡和泡茶的方法步骤都是固定的,只是用到的材料不同,因此可以将泡饮料的方式定义成一个固定的模板
- 1.水烧开
- 2.冲泡饮料
- 3.把饮料倒入杯子
- 4.添加附属配料
-
模板模式即对固定流程模式的操作进行模板化,实现固定的内部方法,抽象出具体的方法,并且可以设置动态的条件
- AbstractClass
- AbstractMethod
- ConcreteClass
- Hook
1.定义模板方法
/**
* 模板模式,制定操作流程,定义抽象方法和具体实现的方法
*/
public abstract class HotDrink {
public final void prepareRecipe() {
boilWater();
brew();
pourInCup();
if (addCondimentsHook()) {
addCondiments();
}
}
/**
* 煮开水是通用的固定方法
*/
public final void boilWater() {
System.out.println("Boiling water");
}
/**
* 添加原材料是抽象的实现的方法
*/
public abstract void brew();
/**
* 放进杯子里是通用的固定方法
*/
public final void pourInCup() {
System.out.println("Pouring into cup");
}
/**
* 添加配料是抽象的需要实现的方法
*/
public abstract void addCondiments();
/**
* 动态变换的条件
*/
public boolean addCondimentsHook() {
return true;
}
}
2.继承模板类,重写具体的自定义方法
/**
* 模板模式,咖啡对象,集成模板方法,实现具体方法
*/
public class Coffee extends HotDrink {
@Override
public void brew() {
System.out.println("Brewing coffee");
}
@Override
public void addCondiments() {
System.out.println("Adding sugar or milk");
}
}
/**
* 模板模式,泡茶对象,集成父类的必须方法,自定义实现具体方法
*/
public class Tea extends HotDrink {
@Override
public void brew() {
System.out.println("Brewing tea");
}
@Override
public void addCondiments() {
System.out.println("Adding lemon");
}
/**
* 自定义的条件,是否需要添加辅料
* @return boolean
*/
@Override
public boolean addCondimentsHook() {
return false;
}
}
3.具体调用
/**
* 模板模式,抽象类制定模板流程,定义抽象方法和具体方法
*/
public class MainTest {
public static void main(String[] args) {
HotDrink coffee = new Coffee();
HotDrink tea = new Tea();
coffee.prepareRecipe();
tea.prepareRecipe();
}
}
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
三、好莱坞原则
好莱坞原则:不要给我们打电话,我们会给你打电话
- 高层无需知道调用底层的细节,解耦
- 降低业务和框架的耦合
- 业务组件可复用,可插拔
四、总结
-
具体细节步骤实现定义在子类中,子类定义详细处理算法是不会改变算法整体结构。
-
代码复用的基本技术,在数据库设计中尤为重要。
-
存在一种反向的控制结构,通过一个父类调用其子类的操作,通过子类对父类进行扩展增加新的行为,符合“开闭原则”。
Java设计模式所有示例代码,持续更新中
网友评论