Java设计模式之模板方法设计模式(银行计息案例)
不知道为什么,这几天对Java中的设计模式非常感兴趣,恰巧呢这几天公司的开发任务还不算太多,趁着有时间昨天又把模板方法模式深入学习了一下,做了一个客户在不同银行计息的小案例,感触颇深,今天给各位分享一下,可能有些常识我在程序中运用的不是很到位,希望各位谅解。
模板方法模式呢,按我意思理解:就是将完成某件事情固定不变的步骤设计成模板类用final修饰的方法,然后将不确定的业务逻辑设计成抽象的方法,目的就是让子类继承并且复写该抽象方法,能够为了实现可扩展性。官方的说法:定义一个操作中算法的框架,而将一些步骤延迟到子类中。模板方法模式使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
模板方法模式是一种基于继承的代码复用技术,它是一种类行为型模式。
模板方法模式是结构最简单的行为型设计模式,在其结构中只存在父类与子类之间的继承关系。通过使用模板方法模式,可以将一些复杂流程的实现步骤封装在一系列基本方法中,在抽象父类中提供一个称之为模板方法的方法来定义这些基本方法的执行次序,而通过其子类来覆盖某些步骤,从而使得相同的算法框架可以有不同的执行结果。模板方法模式提供了一个模板方法来定义算法框架,而某些具体步骤的实现可以在其子类中完成。
好了,读到这儿你估计也懵懵逼逼的,我还是喜欢用事实说话,看码。
【案例一】:就是同一个客户在不同银行分别储蓄了一定金额的存款,2年之后他想知道在每个银行分别能拿到多少本息?(本息=本金+利息)(利息=本金*利率*存期*100%)
设计思想:
通过分析得出,不管他想知道那个银行的本息,都是通过本金+利息的方法得到的,但是问题来了,每个银行计算利息的方式是不同的,当然不是说方式不同而是每个银行根据客户的存期参与计算的利率是不相同的。那么可以根据模板方法模式,可以将计算本息的过程设计成用final修饰的方法,而计算利息的过程可以设计成抽象的方法,然后可以由每个银行类通过继承模板类并复写计算利息的方法来计算出每个银行的利息,最后得出本息。
实现过程:
模板类,将计算本息的过程设计成模板方法,用关键词final修饰(因为用final修饰的方法是不能被复写的,final修饰的变量是不能被重新赋值的,final修饰的类是不能被继承的),然后将计算利息的过程设计成抽象方法,任由子类复写,最后在模板方法中会调用抽象方法,这也是模板设计模式的特性。
/**
* 模板类:每个银行获取本息的方式是固定不变的,但是利息是通过每个银行自己的规定的利率计算得到的。
* 利息=本金*存期*利率
* 本息=本金+利息
*/
abstract class Interest{
/**
* 获取本息
* @param capital:本金
* @return
*/
public final Double getCapital(Double capital){
return capital+getInterest();
}
//获取利息
public abstract Double getInterest();
}
由建设银行和浦发银行分别继承上面的模板类,然后通过各自的利率规则计算出客户的利息,其实这里我的程序并不灵活,假设在实际开发场景中,客户的本金和存期都是由数据库查询出来的。(走到这儿我还有一个小问题想请教各位,就是一直想把每个银行计算利息的那段代码再优化一下,switch语句那块代码把它也想放到final修饰的方法中,但是昨天下班脑子实在转不动了,后期有机会再优化吧)
/**
* 建设银行
*/
class JSBank extends Interest{
//获取指定用户的本金、存期等数据
public double capital = 38654.6;
public int time = 24;
//计算客户利息
@Override
public Double getInterest() {
int num = time/12; //根据用户存期得到年利率
switch(num){
case 1:
return capital*0.0175*num; //一年
case 2:
return capital*0.0225*num; //二年
case 3:
return capital*0.0275*num; //三年
case 5:
return capital*0.0275*num; //五年
}
return capital*0.0135; //未满一年
}
} /**
* 浦发银行
*/
class PFBank extends Interest{
//获取指定用户的本金、存期等数据
public double capital = 38654.6;
public int time = 24;
@Override
public Double getInterest() {
int num = time/12; //根据用户存期得到年利率
switch(num){
case 1:
return capital*0.02*num; //一年
case 2:
return capital*0.024*num; //二年
case 3:
return capital*0.028*num; //三年
case 5:
return capital*0.028*num; //五年
}
return capital*0.0135; //未满一年
}
}
最后来测试一下,我这里的客户是科比 布莱恩特(因为他一直是我的偶像,我喜欢他,喜欢他的性格,喜欢他的一切,他的故事一直在激励着我,一直感谢我生命里有他,请允许我附一张他的图片,哈哈哈~~~):
/**
* 模板设计模式
* 需求:科比分别在建设银行和浦发银行等存蓄一定金额,2年后他想知道他在每个银行的本息是多少?
*/ public class TemplateMethodLiXi { public static void main(String[] args) {
//建行
JSBank js = new JSBank();
Double jsPrincipalAndInterest = js.getCapital(js.capital);
System.out.println("建设银行(科比):"+jsPrincipalAndInterest);
//浦行
PFBank pf = new PFBank();
Double pfPrincipalAndInterest = pf.getCapital(pf.capital);
System.out.println("浦发银行(科比):"+pfPrincipalAndInterest);
} }
【案例二】:计算一段代码的运行时长?
这个案例我不多说设计思想和实现过程,因为实现理念是类似的,请各位赏脸读读鄙人写的代码,它主要就是计算子类继承模板类,然后子类复写抽象方法并实现自己的业务逻辑,最后还是通过模板方法调用抽象方法来灵活达到计算不固定代码块的运行时间。
/**
* 模板方法模式
* 需求:计算自定义类中某个方法(可变的)的运行时长?
*/ public class TemplateMethod {
public static void main(String[] args) {
MyCode my = new MyCode();
Long runtime = my.getTime(); //调用父类的方法获取子类方法的运行时长
System.out.println("运行时间:"+runtime);
}
} /**
* 模板类:计算一段未知代码的运行时长。
*/
abstract class GetCodesRunTime{
/**
* 专门获取一段代码的运行时间
* @return
*/
public final Long getTime(){
long startTime = System.currentTimeMillis(); //开始时间
runCode(); //调用本类抽象方法
long endTime = System.currentTimeMillis(); //终止时间 return endTime-startTime;
}
//由子类复写,然后计算子类方法中代码的运行时长
public abstract void runCode();
} /**
*自定义代码块,继承模板类,然后复写父类的扩展方法
*/
class MyCode extends GetCodesRunTime{
@Override
public void runCode() {
for(int i=0; i<=20000; i++){
System.out.println(i);
}
}
}
设计模式的学习还在继续,后期还会给各位分享其他设计模式的学习心得和案例的实现过程。
Java设计模式之模板方法设计模式(银行计息案例)的更多相关文章
- 11、java中的模板方法设计模式
/* 需求:获取一段程序运行的时间. 原理:获取程序开始和结束的时间并相减即可. 获取时间:System.currentTimeMillis(); 当代码完成优化后,就可以解决这类问题. 这种方式,模 ...
- Java抽象类深入理解-----模板方法设计模式(Templete Method)
模板方法设计模式(Templete Method) 定义一个操作中的算法骨架,而将一些可变部分的实现延迟到子类中. 模板方法设计模式使得子类可以不改变一个算法的结构即可重新定义该算法某些特定的步骤. ...
- [译]Java 设计模式 之模板方法
(文章翻译自Java Design Pattern: Template Method) 模板方法设计模式定义了归档特定操作的工作流.它允许子类去修改特定的步奏而不用改变工作流的结构. 下面的例子表示模 ...
- 折腾Java设计模式之模板方法模式
博客原文地址:折腾Java设计模式之模板方法模式 模板方法模式 Define the skeleton of an algorithm in an operation, deferring some ...
- 设计模式之模板方法模式:实现可扩展性设计(Java示例)
概述 在实际开发中,常常会遇到一项基本功能需要支撑不同业务的情况.比如订单发货,有普通的整包发货,有分销单的发货,采购单的发货,有多商品的整包或拆包发货等.要想支持这些业务的发货,显然不能在一个通用流 ...
- Java设计模式——模板方法设计模式(abstract修饰)
解释: 一个抽象类中,有一个主方法,再定义 1...n 个方法,可以是抽象的,也可以是实际的方法,定义一个类,继承该抽象类,重写抽象方法,通过调用抽象类,实现对子类的调用. 解决的问题: 当功能内部一 ...
- Java基础-Java中23种设计模式之常用的设计模式
Java基础-Java中23种设计模式之常用的设计模式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.设计模式分类 设计模式是针对特定场景给出的专家级的解决方案.总的来说设 ...
- 宋宝华:Linux设备驱动框架里的设计模式之——模板方法(Template Method)
本文系转载,著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 作者: 宋宝华 来源: 微信公众号linux阅码场(id: linuxdev) 前言 <设计模式>这本经典 ...
- 大话设计模式-->模板方法设计模式
在学习java的过程中,我们肯定听到过设计模式这名词,在行业中有这么一句话,若您能熟练的掌握23种设计模式,那么你便是大牛! 好了,废话不多说,今天我跟大家分享一下23种设计模式之一的 模板方法 设 ...
随机推荐
- python不使用第三方变量,交换两个变量的值
#不使用第三个变量交换两个变量的值 a=1 b=2 a,b=b,a#python的直接交换 #另一种交换方法 a=a+b#a=3 b=2 b=a-b#a=3 b=1 a=a-b#a=2 b=1 pri ...
- Dubbo源码分析系列---服务的发布
摘要: 通过解析配置文件,将xml定义的Bean解析并实例化,(涉及重要的类:ServiceBean.RegistryConfig[注册中心配置].ProtocolConfig[协议配置].Appli ...
- 对于JSONObject,我只是临时抱佛脚
说起JSON,大家就谈不上陌生了,因为对于数据传输语言,各位只认json,即使有XML语言,但是各位很少用吧.我也是,但是之前用过的json转换工具各种各样,我记忆中有过GSON(google).fa ...
- js判断是否是ie浏览器且给出ie版本
之前懒得写判断ie版本js,因为网上关于这方面的代码太多了,所以从网上拷贝了一个,放到项目上才发现由于时效性的问题,代码不生效.就自己写一个吧. 怎么去看浏览器的内核等信息 ---- js的全局对象w ...
- spring非controller类获取service方法
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); pushMessageServ ...
- Mac 上Python多版本切换
Mac上自带了Python2.x的版本,有时需要使用Python3.x版本做开发,但不能删了Python2.x,可能引起系统不稳定,那么就需要安装多个版本的Python. 1.安装Python3.x版 ...
- EF编辑
//修改推荐的信息 var productRe = db.Shop_ProductRecommends.Single(item => item.Id == model.Id); productR ...
- Vulkan Tutorial 19 Vertex input description
操作系统:Windows8.1 显卡:Nivida GTX965M 开发工具:Visual Studio 2017 Introduction 在接下来几个章节中,我们将会使用内存顶点缓冲区来替换之前硬 ...
- Ruby中文乱码问题
中文乱码问题 解决方法为只要在文件开头加入 # -*- coding: UTF-8 -*-(EMAC写法) 或者 #coding=utf-8 就行了. 源代码文件中,若包含中文编码,则需要注意两点: ...
- Linq to List
var lstMater = lst.GroupBy(w => new { w.materialId, w.name, w.isPass, w.description }). Select(g ...