1模板方法模式
模板方法模式
模板方法模式(Tempate Method Pattern) 是一种简单的、常见的且应用非常广泛的模式。
1模板方法模式的定义
模板方法模式的英文原文是:
Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template method lets subclasses redefine certain steps of an algorithm whitout changing the algorithm's structure.
翻译过来就是:
定义一个操作中的算法框架,进而推迟一些步骤的执行,将其延迟到子类中。模板方法使得子类不改变算法的结构的情况下,而改变算法。(排序算法、查找算法等)
模板方法涉及到的2个角色:
- 抽象模板(Abstract Template)角色:该角色定义一个或多个抽象操作,以便让子类实现;这些抽象操作是基本操作,是一个顶级逻辑的组成步骤。还需要定义并实现一个或几个模板方法,这些模板方法一般是具体方法,即一个框架,实现对基本方法的调度,完成固定的逻辑。
- 具体模板(Concrete Template)角色:该角色实现抽象模板中定义的一个或多个抽象方法,每一个抽象模板角色都可以有人以多个具体模板角色与之对应,而每一个具体模板角色都可以给出这些抽象方法的不同实现,从而使得顶级逻辑的实现各不相同。
引例
创建抽象方法类
AbstractClass.java
package com.eric.行为型模式.模板方法模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 抽象方法
* @CreateTime 2020-12-05 08:52:29
*/
public abstract class AbstractClass {
//基本方法
protected abstract void operation();
//模板方法
public void templateMethod()
{
//调用基本方法,完成相关的逻辑
this.operation();
}
}
创建模板方法的实现类
ConcreteClass.java
package com.eric.行为型模式.模板方法模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 具体模板方法
* @CreateTime 2020-12-05 08:54:45
*/
public class ConcreteClass extends AbstractClass {
//实现基本业务方法
@Override
protected void operation() {
//业务逻辑
System.out.println("具体的业务逻辑实现方法。");
}
}
创建测试类
Client.java
package com.eric.行为型模式.模板方法模式.引例;
/**
* @author Eric
* @ProjectName my_design_23
* @description 测试类
* @CreateTime 2020-12-05 08:56:06
*/
public class Client {
public static void main(String[] args) {
AbstractClass concreteClass = new ConcreteClass();
//调用模板方法
concreteClass.templateMethod();
}
}
测试结果
2模板方法模式的应用
a.模板方法模式的优点
- 封装不变的部分,扩展可变的部分。不变的部分封装到父类中实现,而可变的部分则可通过继承进行扩展。
- 提取公共部分代码,便于维护。将公共部分的代码抽取出来放在父类中,维护时只需要修改父类中的代码。
- 行为由父类控制,子类实现。模板方法模式中的基本方法是由子类实现的,因此子类可以通过扩展增加相应的功能,符合开闭原则。
b.模板方法模式的使用场景
- 多个子类有公共方法,并且逻辑基本相同。
- 可以把重要的、复杂的、核心的算法设计为模板方法,周边的相关细节功能则由各个子类实现。
- 重构时,模板方法模式是一个经常使用的模式,将相同的代码抽取到父类中。
3模板方法实例
使用模板方法模式,计算银行活期和定期账户的利息。
由于利息计算是两个步骤:
- 确定账户类型,是活期账户,还是定期账户;
- 确定利息的百分比。
这两个基本的方法抽象到模板类Account中,而具体的实现步骤留给具体的模板类,即Account的子类DemandAccount和FixedAccount来实现。
模拟银行利率计算的类图
创建抽象模板方法:
确定账户类型方法、确定利息的抽象方法交给子类实现。模板方法来计算账户利息。
Account.java
package com.eric.行为型模式.模板方法模式.例1;
import java.math.BigDecimal;
/**
* @author Eric
* @ProjectName my_design_23
* @description 抽象模板方法,抽象账户类
* @CreateTime 2020-12-05 12:46:29
*/
public abstract class Account {
//账号
private String username;
//构造函数
public Account(String username){
this.username = username;
}
//抽象方法,留给子类实现
//基本方法
//确定账户类型
public abstract String getAccountType();
//确定利息
public abstract double getAccountRate();
//根据账户类型和账号确定账户金额
public double getAccountMoney(String accountType,String username)
{
//模拟从数据库取值
return 3279.0D;
}
//模板方法,计算账户利息
public String calculateInterest(){
//获得账户类型
String accountType = getAccountType();
//获得比率
double accountRate = getAccountRate();
//获得账户余额
double accountMoney = getAccountMoney(accountType, username);
//账户余额*利率
return username+"账户的利息为"+accountMoney*accountRate;
}
}
创建定期和活期账户的实现类,并具体实现抽象模板方法。
DemandAccount.java
package com.eric.行为型模式.模板方法模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 活期存款
* @CreateTime 2020-12-05 13:05:49
*/
public class DemandAccount extends Account {
public DemandAccount(String username) {
super(username);
}
@Override
public String getAccountType() {
return "活期";
}
@Override
public double getAccountRate() {
return 0.005;
}
}
FixedAccount.java
package com.eric.行为型模式.模板方法模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 定期(1年)
* @CreateTime 2020-12-05 13:06:56
*/
public class FixedAccount extends Account {
public FixedAccount(String username) {
super(username);
}
@Override
public String getAccountType() {
return "定期一年";
}
@Override
public double getAccountRate() {
return 0.035;
}
}
创建测试类
Client.java
package com.eric.行为型模式.模板方法模式.例1;
/**
* @author Eric
* @ProjectName my_design_23
* @description 测试类
* @CreateTime 2020-12-05 13:07:49
*/
public class Client {
public static void main(String[] args) {
//活期账户
Account demandAccount = new DemandAccount("张三");
System.out.println(demandAccount.calculateInterest());
// 定期账户
Account fixedAccount = new FixedAccount("王二麻子");
System.out.println(fixedAccount.calculateInterest());
}
}
只要你不停下来,慢一点也没关系。