Design Patterns——Template Method入门到情景实战

Template Method

什么是Template Method

Template Method的设计思想

简单的说,就是为了不在多个子类实现某个算法的过程当中,应用程序开发人员写错了算法过程,而致使产生了错误的结果。咱们让类库开发人员本身写一个固定的算法骨架(因而此模式只能适应于算法骨架基本肯定的应用场景!)。让一部分全部类都公用的算法、步骤,在类库中实现,而后让不一样的应用程序开发人员书写适用于当前场景的部分步骤,而后调用父类的骨架方法,实现算法!java

在Template Method设计模式中有哪些类型的方法

第一:交给类库实现的,应用程序开发人员不能修改的固定的方法

好比下面的实战1的银行业务办理程序,取号、业务结束给出评价,这两个步骤是不一样的应用程序不须要管理的,因而设置为final的(在Java程序设计中是final,若是是c++程序设计则把函数实现写成const便可!)。这些程序每每是一些和任何应用程序开发者无关的代码,设置成final避免应用程序开发者无心中修改,致使了算法的结果错误!c++

第二:交给类库实现的,可是应用程序开发人员可根据实际状况,考虑修改或者不修改的

好比下面的实战2的数据分析程序,有些应用程序(子类)的应用场景下的数据,须要被加工再能被分析!可是有些数据是能够直接拿来分析,好比:Excel的数据每每能够在download后直接拿来处理,可是一些柱状图制类的数据须要二次加工后再处理!因此咱们能够设置一个《钩子函数》的hook方法,这种方法通常是返回布尔值的(boolean/bool)。若是大多数状况是须要处理的,咱们就给这个hook方法默认返回一个false,避免有些应用程序开发者忘记处理而进入数据分析的流程!若是当前的数据是不须要二次加工的,则拓展的子类重写该方法,返回true便可!算法

第三:交给应用程序开发者实现的,在抽象类中无论的抽象方法

抽象方法在Java中,以关键字abstract来体现,有abstract标注的方法的类,称之为抽象类。若是是在c++中,则是设置纯虚函数,有纯虚函数的类是抽象类。这个方法咱们不能拿来实现,只须要在父类中定义,而后编译器会强制要去应用程序的开发者去根据本身的实际状况来实现抽象类。起到在运行期多态的效果!编程

使用 Template Method的好处

让算法固定,达到一种父类去调用子类的效果,符合《开闭原则》!
又利用继承与多态,达到算法骨架的代码复用的效果!设计模式

模板方法相关实战1:银行业务办理程序

设计分析:

在银行办理业务这个算法流程(骨架)中,有一下几个步骤:
① 取号
② 办理业务
③ 业务结束,给出本次业务的评价markdown

其中有一些过程(方法)是静态的,就是取号、业务结束,这两个步骤。可是办理业务的过程是动态的,不一样的用户角色,想办理不一样的业务!因此咱们只能把这个动态的过程(方法)抽象化,而固定不变的算法骨架。让不一样的须要办理业务的角色类去继承这个抽象类,而后在子类中重写须要办理的业务,在重写结束后,再在调用的主类中去调用整个算法骨架process()。根据多态性,会根据子类的不一样、实现的办理业务的程序的不一样,在相同的算法骨架中获得不一样的结果!ide

个人抽象父类:BankTranscation

/** * 这个抽象类做为模板方法的父类,完成银行业务 * @author 不会编程的小良 * @version 1.0 * */
abstract class BaseBankTranscation {

    static int ServerId = 1;

    public void takeNumber(){
        System.out.println("排队取号ing……");
    }

    /** * 这个抽象函数负责由子类根据具体业务完成重写 * @author 不会编程的小良 * @version 1.0 * */
    public abstract void transcation();

    public void evalue(){
        System.out.println("第 " + ServerId + " 次服务结束,完成评分……");
    }

    public final void process(){
        System.out.println("开始第 " + ServerId + " 次服务!");
        takeNumber();
        transcation();
        evalue();
        ServerId++;
    }

}

不一样业务办理的子类

/** * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成取款业务 * @author 不会编程的小良 * @version 1.0 * */
class Deposite extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要取款……");
    }
}

/** * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成存款业务 * @author 不会编程的小良 * @version 1.0 * */
class Withdraw extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要存款……");
    }
}

/** * 这个子类负责重写父类BaseBankTranscation的方法transcation(),完成转帐业务 * @author 不会编程的小良 * @version 1.0 * */
class Transfer extends BaseBankTranscation {

    @Override
    public void transcation() {
        System.out.println("我要转帐……");
    }
}

主类调用各个子类的process方法,完成业务办理

/** * 这个主类负责完成各类银行业务的办理过程 * @author 不会编程的小良 * @version 1.0 * */
public class TemplateMethod {

    public static void main(String[] args){

        int n = 3;
        BaseBankTranscation[] tran = new BaseBankTranscation[n];
        for(int i = 0;i < n;++i){
            switch (i % 3){
                case 0:
                    tran[i] = new Deposite();
                    break;
                case 1:
                    tran[i] = new Withdraw();
                    break;
                case 2:
                    tran[i] = new Transfer();
                    break;
                default:
                    break;
            }
        }
        for(BaseBankTranscation item : tran) {
            item.process();
        }

    }
}

执行的结果是:

在这里插入图片描述

模板方法相关实战2:数据处理与分析案例

设计分析:

这个数据处理与分析分红几个步骤:函数

① 数据获取(应用程序完成的抽象方法)
② 数据转换成可处理的模式 (hook方法)
③ 数据分析(应用程序完成的抽象方法)
④ 数据分析的结果展现(hook方法)测试

父类BaseDataAnalysis的实现

abstract class BaseDataAnalysis {

    abstract void getData();

    void connvertData(){
        System.out.println("默认的数据转换方法……");
    }

    final void analysisData(){
        System.out.println("完成数据分析工做……");
    }

    void displayData(){
        System.out.println("默认的输出方式展现……");
    }

    boolean isValid(){
        return true;
    }

    void process(){
        getData();
        if(isValid()){
            connvertData();
        }
        analysisData();
        displayData();
    }

}

拓展出来的子类SubClass实现

class SubClass extends BaseDataAnalysis {

    @Override
    void getData(){
        System.out.println("从JSON文件中获取数据……");
    }

    @Override
    void displayData(){
        System.out.println("以饼状图展现的方法展现……");
    }
}

主类的测试方法执行

public class TemplateMethod {
    public static void main(String[] args){
        BaseDataAnalysis sub = new SubClass();
        sub.process();
    }
}

执行的结果是:

在这里插入图片描述

思考与练习

问题描述:

某银行软件的利息计算流程以下:atom

① 系统根据帐户查询用户信息

② 根据用户信息来判断用户类型

③ 不一样类型的用户使用不一样的利息计算方式(如活期、按期)

④ 显示利息

个人解决方案——抽象银行利息类:

abstract class BankInterest {

    boolean isValidUser(String username, String password){
        if("jiangzhengliang".equals(username) && "123456".equals(password)) {
            System.out.println("帐户:" + username);
            System.out.println("密码:" + password);
            return true;
        }
        else {
            return false;
        }
    }

    abstract void getAccountMethod();

    final void display(){
        System.out.println("显示利息……");
    }

    void process(String name, String psswd){
        if(isValidUser(name, psswd)){
            getAccountMethod();
            display();
        }
    }

}

个人解决方案——拓展的活期、按期利息子类

class CurrentAccount extends BankInterest {

    @Override
    void getAccountMethod() {
        System.out.println("我是活期贷款……");
    }
}

class SavingAccount extends BankInterest {

    @Override
    void getAccountMethod() {
        System.out.println("我是按期贷款……");
    }
}

个人解决方案——测试主类

public class TemplateMethod {
    public static void main(String[] args){
        BankInterest bank1 = new CurrentAccount();
        bank1.process("jiangzhengliang", "123456");

        BankInterest bank2 = new SavingAccount();
        bank2.process("jiangzhengliang", "123456");
    }
}

测试的结果:

在这里插入图片描述

相关文章
相关标签/搜索