1. 设计模式之模板方法模式:抽取通用代码逻辑到父类
1.1. 介绍
在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。这种类型的设计模式属于行为型模式。
解决在多个子类中重复实现相同的方法的问题,通过将通用方法抽象到父类中来避免代码重复。
优缺点及建议
优点
1.封装不变部分:算法的不变部分被封装在父类中。
2.扩展可变部分:子类可以扩展或修改算法的可变部分。
3.提取公共代码:减少代码重复,便于维护。
缺点
1.类数目增加:每个不同的实现都需要一个子类,可能导致系统庞大。
使用建议
1.当有多个子类共有的方法且逻辑相同时,考虑使用模板方法模式。
2.对于重要或复杂的方法,可以考虑作为模板方法定义在父类中。
注意事项
1.为了防止恶意修改,模板方法通常使用final关键字修饰,避免被子类重写。
1.2. 实现及相关代码
假设有一个业务,开发优惠券逻辑,优惠券种类有很多,都会有一段通用逻辑,然后每种优惠券都有自己特殊的逻辑。
1.2.1. 没使用设计模式方式
接口及数据对象
public static class DiscountCalculator1 {
public void calculate() {
System.out.println("通用的计算逻辑");
System.out.println("优惠计算器1的特殊计算逻辑");
}
}
public static class DiscountCalculator2 {
public void calculate() {
System.out.println("通用的计算逻辑");
System.out.println("优惠计算器2的特殊计算逻辑");
}
}
public static class DiscountCalculator3 {
public void calculate() {
System.out.println("通用的计算逻辑");
System.out.println("优惠计算器3的特殊计算逻辑");
}
}
调用方法
public static void main(String[] args) {
DiscountCalculator1 calculator1 = new DiscountCalculator1();
calculator1.calculate();
DiscountCalculator2 calculator2 = new DiscountCalculator2();
calculator2.calculate();
DiscountCalculator3 calculator3 = new DiscountCalculator3();
calculator3.calculate();
}
可能会遇到的问题
各种优惠券都有通用的逻辑,如果通用逻辑要调整,需要改各类优惠券的代码,当种类很多的时候,很容易有遗漏。修改遗漏会引发很严重的问题,导致价格计算错误,会有严重的损失。扩展性、维护性很差。
1.2.2. 使用设计模式方式
使用模版方法设计模式,可以把通用逻辑抽象出来,各类优惠券可以公用复用,当要调整逻辑时,只修改一个地方,所有优惠券都会生效,不会有遗漏。
接口及数据对象
public interface DiscountCalculator {
void calculate();
}
/** 模板方法实现的精华所在 */
public static abstract class AbstractDiscountCalculator implements DiscountCalculator {
public void calculate() {
// 完成通用的计算逻辑
commonCalculate();
// 完成特殊的计算逻辑
specificCalculate();
}
private void commonCalculate() {
System.out.println("通用的计算逻辑");
}
protected abstract void specificCalculate();
}
public static class DiscountCalculator1 extends AbstractDiscountCalculator {
public void specificCalculate() {
System.out.println("优惠计算器1的特殊计算逻辑");
}
}
public static class DiscountCalculator2 extends AbstractDiscountCalculator {
public void specificCalculate() {
System.out.println("优惠计算器2的特殊计算逻辑");
}
}
public static class DiscountCalculator3 extends AbstractDiscountCalculator {
public void specificCalculate() {
System.out.println("优惠计算器3的特殊计算逻辑");
}
}
调用方法
public static void main(String[] args) {
DiscountCalculator calculator1 = new DiscountCalculator1();
calculator1.calculate();
DiscountCalculator calculator2 = new DiscountCalculator2();
calculator2.calculate();
DiscountCalculator calculator3 = new DiscountCalculator3();
calculator3.calculate();
}