设计模式之模板方法模式

模板方法模式:定义一个算法中的操作框架,而将一些步骤延迟到子类中。使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
通俗来将就是一个固定流程的功能,将公共的流程部分提取到父类中来实现,子类实现其他流程,同时在父类中执行整个流程(也就是说父类中规定了方法的执行流程,而方法的具体实现有子类去决定)。

在模板模式(Template Pattern)中,一个抽象类公开定义了执行它的方法的方式/模板。它的子类可以按需要重写方法实现,但调用将以抽象类中定义的方式进行。
这种类型的设计模式属于行为型模式。

场景示例

各个种类的商品有不同的优惠政策,在下单时需要根据优惠政策计算订单金额。

如果不使用模版方法模式,那么通常就是对每个种类的商品写一个优惠计算的方法实现。
但是如果各个种类的商品的其他费用的计算规则一样的,此时每个的计算方法都需要去实现这个方法(当然我们可以将这部分实现单独提取到一个方法,这里直接调用即可);
如果各个计算方法具有关联性(即执行的方法2需要方法1的执行结果),那么一旦这个关联规则发生改变则每个方法都需要去修改;此时就体现出模版方法的优势了。

示例代码

public static void main(String[] args) {
    GoodsService fruitService = new FruitService();
    fruitService.calculate(10);
    System.out.println("======================");
    GoodsService homeAppliancesService = new HomeAppliancesService();
    homeAppliancesService.calculate(12);
}

interface GoodsService {

    /**
     * 计算金额
     * @param amount 购买数量
     */
    void calculate(int amount);
}

/**
 * 模板方法实现
 */
static abstract class AbstractGoodsService implements GoodsService {

    /**
     * 这里设计 计算流程规则
     */
    @Override
    public void calculate(int amount) {
        // 完成通用的逻辑
        BigDecimal money = commonCalculate();
        // 完成特殊的逻辑
        money = money.add(specificCalculate(amount));
        System.out.println("共计:"+money);
        // 其他操作....
    }
    private BigDecimal commonCalculate() {
        System.out.println("执行公共费用计算:...");
        return new BigDecimal("2.00");
    }

    /**
     * 特殊的计算逻辑
     * @param amount 购买数量
     * @return 返回金额
     */
    protected abstract BigDecimal specificCalculate(int amount);
}

static class FruitService extends AbstractGoodsService {
    @Override
    public BigDecimal specificCalculate(int amount) {
        System.out.println("执行水果类商品的优惠政策");
        return new BigDecimal("0.99").multiply(new BigDecimal(String.valueOf(amount)));
    }
}

static class HomeAppliancesService extends AbstractGoodsService {
    @Override
    public BigDecimal specificCalculate(int amount) {
        System.out.println("执行家电类商品的优惠政策");
        return new BigDecimal("0.8").multiply(new BigDecimal(String.valueOf(amount)));
    }
}

AbstractGoodsService类中定义执行流程,当需要修改流程时直接改这个类即可;对应商品折扣类型、优惠政策等非常的适用

posted @ 2020-09-25 23:06  起岸星辰  阅读(123)  评论(0编辑  收藏  举报