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模板方法实例
使用模板方法模式,计算银行活期和定期账户的利息。
由于利息计算是两个步骤:
  1. 确定账户类型,是活期账户,还是定期账户;
  2. 确定利息的百分比。
这两个基本的方法抽象到模板类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());

    }
}




posted @ 2020-12-29 12:12  喵酱张-Eric  阅读(73)  评论(0编辑  收藏  举报