曾经在银行做过增值税管理系统,对于财务会计上的增值税的计算,需要严格按照(卖出价-买入价)* 税率来计算,也就是说,我们需要这样一个流程,我们需要先统计整个卖出价格,再统计出整个买入价格,然后作差后,再乘以税率。必须符合整个流程顺序,这样的一个流程就比较符合模板方法模式了。
模板方法模式(Template Method Pattern):
准备一个抽象类,将部分逻辑以具体方法以及具体构造函数的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。比如定义一个操作中的算法的骨架,将步骤延迟到子类中。模板方法使得子类能够不去改变一个算法的结构即可重定义算法的某些特定步骤。
对应类图如下:
模板方法模式的组成:
AbstractClass:超类方法,该方法中定义了模板方法和一些算法的骨架
ContreateClass:子类方法,实现超类方法中的某些算法
HookMethod:钩子方法,实现对子类方法中逻辑的改变控制
具体代码:
AbstractClass:
public abstract class AbstractClass {
//模板方法
final public void templateMehod(){
this.countIncome();
this.countOutcome();
if(this.isTax()){
this.tax();
}
}
protected abstract void countIncome();
protected abstract void countOutcome();
protected abstract void tax();
//钩子方法
protected boolean isTax(){
return true;
}
}
ContreateClass:
public class ContreteClass extends AbstractClass {
private boolean rate = true;
public boolean isRate() {
return rate;
}
public void setRate(boolean rate) {
this.rate = rate;
}
@Override
protected void countIncome() {
System.out.println("本季度收入为90W");
}
@Override
protected void countOutcome() {
System.out.println("本季度支出为50W");
}
@Override
protected void tax() {
System.out.println("计算税率");
}
@Override
protected boolean isTax(){
return this.rate;
}
}
验证:
public class Client {
public static void main(String[] args) {
ContreteClass a = new ContreteClass();
a.templateMehod();
ContreteClass v = new ContreteClass();
v.setRate(false);
v.templateMehod();
}
}
结果:
在模板方法模式中,由于面向对象的多态性,子类对象在运行时将覆盖父类对象,子类中定义的方法也将覆盖父类中定义的方法,因此程序在运行时,具体子类的基本方法将覆盖父类中定义的基本方法,子类的钩子方法也将覆盖父类的钩子方法,从而可以通过在子类中实现的钩子方法对父类方法的执行进行约束,实现子类对父类行为的反向控制。
优点:
缺点:
每个不同的实现都需要定义一个子类,这会导致类的个数的增加,设计更加抽象。
适用场景: