整体算法的设计是一个抽象类, 它有一系列抽象方法, 代表算法中可被定制的步骤, 同时这个类中包含了一些通用代码。 算法的每一个变种由具体的类实现, 它们重写了抽象方法, 提供了相应的实现。
模板方法模式通过把不变的行为搬移到超类,去除了子类中的重复代码。子类实现算法的某些细节,有助于算法的扩展。通过一个父类调用子类实现的操作,通过子类扩展增加新的行为,符合“开放-封闭原则”。
示例:
假设有一个检查流程,要检查身份信息,信用信息,收入情况。这些信息来源不同,如检查公司和个人的信息情况,那么对于不同的来源信息,检查方法不同,但是检查流程是统一的,如定义个流程(或者是优先级) 检查身份信息-->信用信息-->收入情况。
代码实现:
public class TemplateTest{
/**
* 检查使用的模板
*/
static abstract class CheckTemplate {
//检查身份信息
protected abstract void identity();
//检查信用信息
protected abstract void creditHistory();
//检查收入信息
protected abstract void incomeHistory();
//检查流程定义
public void check(){
this.identity();
this.creditHistory();
this.incomeHistory();
}
}
/**
* 检查模式的基类,提供默认的实现
*/
static class CheckTemplateBase extends CheckTemplate{
@Override
protected void identity() {
System.out.println("basecheck identity");
}
@Override
protected void creditHistory() {
System.out.println("basecheck creditHistory");
}
@Override
protected void incomeHistory() {
System.out.println("basecheck incomeHistory");
}
}
static class CheckCompany extends CheckTemplateBase{
@Override
protected void incomeHistory() {
System.out.println("check company");
}
}
//测试
public static void main(String[] args) {
CheckCompany checkCompany = new CheckCompany();
checkCompany.check();
}
}
说明:
1、定义一个检查模板CheckTemplate ,模板中定义了 protected 的抽象检查方法,主要是不对外提供调用。check() 方法提供是的检查流程。
2、声明检查模板接着声明检查的基类 CheckTemplateBase ,主要为了提供一个默认的实现,所有的检查类可以继承这个基类。
3、最后就是具体的要检查的类型 CheckCompany 继承 CheckTemplateBase 类,可以实现具体的检查方式。
java8 函数jdk8 函数式编程实现,使用“函数接口”
代码:
public class TemplateTest{
/**
* 函数接口
*/
interface Criteria{
void check();
}
/**
* 模板
*/
static class CheckTemplate {
//函数接口 作为属性
private final Criteria identity;
private final Criteria creditHistory;
private final Criteria incomeHistory;
public CheckTemplate(Criteria identity,
Criteria creditHistory,
Criteria incomeHistory) {
this.identity = identity;
this.creditHistory = creditHistory;
this.incomeHistory = incomeHistory;
}
//模板方法
public void checkLoanApplication(){
identity.check();
creditHistory.check();
incomeHistory.check();
}
}
/**
* 默认的检查类,每一个方法,都对应一个 函数接口
* 所有的处理子类实现可以继承此类
*/
static class CheckBase {
public void identity() {
System.out.println("basecheck identity");
}
public void creditHistory() {
System.out.println("basecheck creditHistory");
}
public void incomeHistory() {
System.out.println("basecheck incomeHistory");
}
}
/**
* 检查
*/
static class Check extends CheckTemplate {
public Check(CheckBase check) {
//传入都是函数接口
super(check::identity,
check::creditHistory,
check::incomeHistory);
}
}
/**
* Company 处理流程
*
*/
static class CompanyCheck extends CheckBase {
//重写 creditHistory 方法
public void creditHistory(){
System.out.println("company creditHistory ");
}
}
public static void main(String[] args) {
Check c = new Check(new CompanyCheck());
c.checkLoanApplication();
}
}
说明:
3、检查的基类 CheckBase 主要为了提供一个默认的实现,所有的检查类可以继承这个基类。
4、声明具体检查 CompanyCheck extends CheckBase,可以自定义检查的内容,如果不定义就使用默认的。
5、声明检查类 Check extends CheckTemplate ,声明了一个构造方法参数是检查基类(接口也可以) CheckBase。有两个作用:a:用于所有的具休检查类的基类,b:Check 构造方法的参数,只要是CheckBase 子类就可以构造Check ,代码清晰规范。在构造方法中,直接调用父类的构造方法,参数就是“函数接口”。
java8终极代码:
public class TemplateTest{
/**
* 函数接口
*/
interface Criteria{
void check();
}
/**
* 模板
*/
static class CheckTemplate {
//函数接口 作为属性
private final Criteria identity;
private final Criteria creditHistory;
private final Criteria incomeHistory;
public CheckTemplate(Criteria identity,
Criteria creditHistory,
Criteria incomeHistory) {
this.identity = identity;
this.creditHistory = creditHistory;
this.incomeHistory = incomeHistory;
}
//模板方法
public void checkLoanApplication(){
identity.check();
creditHistory.check();
incomeHistory.check();
}
}
/**
* 默认的检查类,每一个方法,都对应一个 函数接口
* 所有的处理子类实现可以继承此类
*/
static class CheckBase {
public void companyIdentity() {
System.out.println("company identity");
}
public void companyCreditHistory() {
System.out.println("company creditHistory");
}
public void companyIncomeHistory() {
System.out.println("company incomeHistory");
}
//大公司的收入检查
public void bigCompanyIncomeHistory() {
System.out.println("big company incomeHistory");
}
}
public static void main(String[] args) {
CheckBase checkBase = new CheckBase();
CheckTemplate checkTemplate = new CheckTemplate(checkBase::companyIdentity,checkBase::companyCreditHistory,checkBase::bigCompanyIncomeHistory);
checkTemplate.checkLoanApplication();
}
}
两种实现方式比较:
第一种实现要每一个要检查的对象都要被创建一个具体的类,而java8的实现可以直接传入“函数接口”。
在示例中声明了一个具体的类,也可以把所有查检方式(具体方法)都声明在CheckBase 类中,根据不同的检查对象直接传入“函数”就可以,这样就避免为每一个检查对象创建一个类。