package com.day28.test;

public class Test {
    public static void main(String[] args) {
        System.out.println("模板方法的设计模式及应用场景");
        // 当有些非常清晰的逻辑 可以直接通过方法来实现
        // 如果此类还有一些不确定的因素 而无法进行实现
        // 就可以使用 这种设计模式 来解决 
        // 此类 可以把这些不确定的内容 声明成  抽象方法 
        // 然后在子类中实现 真正的逻辑处理
        Template template= new SubTemplate();
        template.spendTime();
        
        //测试银行类
        //取钱
        BankTemplateMethod bankTemplateMethod=new drawMoney();
        bankTemplateMethod.process();
        
        //理财
        BankTemplateMethod bankTemplateMethod2=new makeMoney();
        bankTemplateMethod2.process();
        
        //模板方法 在编程中 经常用到的设计模式
        //各种框架 和类库里都有他的影子
        // 数据库访问的封装
        // Junit 单元测试 
        // JavaWeb 的Servlet中关于doGet /doPost方法的调用
        // Hibernate中模板程序
        // Spring 中的JDBCTemlate HibernateTemplate等
    }

}

//例子一

abstract class Template{
    
    //计算某段代码执行所花费的时间
    public void spendTime() {
        
        long start=System.currentTimeMillis();
        code(); //不确定的部分 定义为抽象类
        long end =System.currentTimeMillis();
        
        System.out.println("调用函数花费时间"+(end-start));
        
    
        
    }
    
    public abstract void code();
}

class SubTemplate extends Template{
    
    //重写方法
    @Override
    public void code() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 1000; i++) {
            System.out.println(i);
            
        }
    } 
    

}

//例子二
//现在有一家银行
//银行的操作如下:
// 取号、办业务、 评价
// 这里的取号 和评价 在银行流程中 是可以确定的 每个人来到银行都会进行这两步操作
// 但是 这里的 办业务 就有所不同了 
//  也许有人会来银行取款 
//  也许有人会来银行理财 等等
//  所以说 办业务这个方法 在银行这个类中就不能具体实现
//  要针对不同的人 操作不同的业务 
//  所以 可以把此类定义为 抽象方法 通过子类来实现具体操作

abstract class BankTemplateMethod{
    //具体方法
    //取号
    public void taskNumber() {
        System.out.println("取号排队");
    }
    
    //办业务 抽象方法
    public abstract void transact();  // 钩子方法  办理具体业务
    
    //评价
    public void evaluate() {
        System.out.println("反馈评分");
    }
    
    //模板方法  巧妙的设计
    // 可以把一串的业务流程怎么执行 定义到这个方法里 直接调用这个方法 即可
    // 这个方法 使用 final(最终的) 关键字 修饰  不能被重写 因为每个人到银行都需要做这几步  
    public final void process() {
        //取号
        this.taskNumber();
        // 办业务  钩子方法 回调方法
        this.transact();   //像钩子一样 具体实现时 挂哪个子类 就执行哪个子类的实现代码
        // 评价
        this.evaluate();
    }
}

//取钱类
class drawMoney extends BankTemplateMethod{

    // 重写父类抽象方法
    @Override
    public void transact() {
        // TODO Auto-generated method stub
        
        System.out.println("我来取钱了");
        
    }
    
}
//理财类
class makeMoney extends BankTemplateMethod{

    // 重写父类抽象方法
    @Override
    public void transact() {
        // TODO Auto-generated method stub
        System.out.println("我来理财了");
        
    }
    
}