模板方法模式-阿里云开发者社区

开发者社区> javaedge> 正文

模板方法模式

简介: 开发软件时一个常见的情况是有一个通用的算法,只是步骤上略有不同。我们希望不同的 实现能够遵守通用模式,保证它们使用了同一个算法,也是为了让代码更加易读。一旦你 从整体上理解了算法,就能更容易理解其各种实现。
+关注继续查看

开发软件时一个常见的情况是有一个通用的算法,只是步骤上略有不同。我们希望不同的 实现能够遵守通用模式,保证它们使用了同一个算法,也是为了让代码更加易读。一旦你 从整体上理解了算法,就能更容易理解其各种实现。

 模板方法模式是为这些情况设计的:整体算法的设计是一个抽象类,它有一系列抽象方法,代表算法中可被定制的步骤,同时这个类中包含了一些通用代码。算法的每一个变种 由具体的类实现,它们重写了抽象方法,提供了相应的实现。 

让我们假想一个情境来搞明白这是怎么回事。假设我们是一家银行,需要对公众、公司和 职员放贷。放贷程序大体一致即验明身份、信用记录和收入记录。这些信息来源不一, 衡量标准也不一样。你可以查看一个家庭的账单来核对个人身份;公司都在官方机构注册 过,比如美国的SEC、英国的Companies House。 

我们先使用一个抽象类LoanApplication 来控制算法结构,该类包含一些贷款调查结果 报告的通用代码。根据不同的申请人,有不同的类:CompanyLoanApplication、Personal LoanApplication 和EmployeeLoanApplication。图1 展示了LoanApplication 类的结构。


img_f31932f27aae7db6b13dd8ce6fe244a9.png
图1 使用模板方法模式描述申请贷款过程


CompanyLoanApplication 的checkIdentity 方法在Companies House 等注册公司数据库中查找相关信息。checkIncomeHistory 方法评估公司的现有利润、损益表和资产负债表。checkCreditHistory 方法则查看现有的坏账和未偿债务。

PersonalLoanApplication 的checkIdentity 方法通过分析客户提供的纸本结算单,确认客户地址是否真实有效。checkIncomeHistory 方法通过检查工资条判断客户是否仍被雇佣。checkCreditHistory 方法则会将工作交给外部的信用卡支付提供商。

EmployeeLoanApplication 就是没有查阅员工历史功能的PersonalLoanApplication。为了方便起见,我们的银行在雇佣员工时会查阅所有员工的收入记录图 2。

img_5568e4ee952b35380e2213212c753337.png
图2 员工申请贷款是个人申请的一种特殊情况


使用Lambda 表达式和方法引用,我们能换个角度思考模板方法模式,实现方式也跟以前不一样。模板方法模式真正要做的是将一组方法调用按一定顺序组织起来。如果用函数接口表示函数,用Lambda 表达式或者方法引用实现这些接口,相比使用继承构建算法,就会得到极大的灵活性。让我们看看如何使用这种方式实现LoanApplication 算法,请看图3


img_49b6d3feba3157d545c771482530f5c1.png
图3 员工申请贷款的例子


正如读者所见, 这里没有使用一系列的抽象方法, 而是多出一些属性:identity、creditHistory 和incomeHistory。每一个属性都实现了函数接口Criteria,该接口检查一项标准,如果不达标就抛出一个问题域里的异常。我们也可以选择从check 方法返回一个类来表示成功或失败,但是沿用异常更加符合先前的实现图4。


img_ab8a8a794e8f5050c41d6659fc88b157.png
图4  如果申请失败,函数接口Criteria 抛出异常


采用这种方式,而不是基于继承的模式的好处是不需要在LoanApplication 及其子类中实现算法,分配功能时有了更大的灵活性。比如,我们想让Company 类负责所有的检查,那么Company 类就会多出一系列方法,如图5。


img_a2ed0da5c79ead033859dcf9a2f002c5.png
图5 Company 类中的检查方法


现在只需为CompanyLoanApplication 类传入对应的方法引用,如图6。


img_3ff433b7218cf6610971139f01924984.png
图6 CompanyLoanApplication 类声明了对应的检查方法


将行为分配给Company 类的原因是各个国家之间确认公司信息的方式不同。在英国,Companies House 规范了注册公司信息的地址,但在美国,各个州的政策是不一样的。

使用函数接口实现检查方法并没有排除继承的方式。我们可以显式地在这些类中使用Lambda 表达式或者方法引用。

我们也不需要强制EmployeeLoanApplication 继承PersonalLoanApplication 来达到复用,可以对同一个方法传递引用。它们之间是否天然存在继承关系取决于员工的借贷是否是普通人借贷这种特殊情况,或者是另外一种不同类型的借贷。因此,使用这种方式能让我们更加紧密地为问题建模。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
4398 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
5722 0
python设计模式(十四):模板方法模式
定义一个算法或者流程,部分环节设计为外部可变,用类似于模板的思想来实例化一个实体,可以往模板中填充不同的内容;在模板思想下,实体的整体框架是确定的,他是一个模板,但是模板下内容可变,从而实现了动态的更新流程或算法。
754 0
+关注
522
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载