设计模式之模板方法模式

概述

模板模式通常又叫模板方法模式(Template Method Pattern)是指定义一个算法的骨架,并允许子类为一个或者多个步骤提供实现。模板方法使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤,属于行为性设计模式。

适用于:
1、一次性实现一个算法的不变的部分,并将可变的行为留给子类来实现。
2、各子类中公共的行为被提取出来并集中到一个公共的父类中,从而避免代码重复。

我们以炒菜为例子:
洗锅–>点火–>热锅–>上油–>下原料–>翻炒–>放调料–>出锅;

流程:
洗锅、点火、热锅、上油、翻炒、出锅都是一样的。
下原料和放调料是不一样的。
如果不使用模板模式:

炒菜接口:

public interface StirFry {

    void washingPot();

    void onFire();

    void hotPot();

    void pushOil();

    void pushRawMaterial();

    void Stir();

    void pushSeasoning();

    void outPot();

    void stirFry();
}

//两个实现类:

public class StirPork implements StirFry{


    @Override
    public void washingPot() {
        System.out.println("洗锅");
    }

    @Override
    public void onFire() {
        System.out.println("点火");
    }

    @Override
    public void hotPot() {
        System.out.println("热锅");
    }

    @Override
    public void pushOil() {
        System.out.println("放油");
    }

    @Override
    public void pushRawMaterial() {
        System.out.println("放原料猪肉");
    }

    @Override
    public void Stir() {
        System.out.println("翻炒");
    }

    @Override
    public void pushSeasoning() {
        System.out.println("放调料,盐,酱油");
    }

    @Override
    public void outPot() {
        System.out.println("出锅");
    }
    @Override
    public void stirFry() {
        washingPot();
        onFire();
        hotPot();
        pushOil();
        pushRawMaterial();
        Stir();
        pushSeasoning();
        outPot();
    }
}



public class StirSweetSourSpareribs implements StirFry{
    @Override
    public void washingPot() {
        System.out.println("洗锅");
    }

    @Override
    public void onFire() {
        System.out.println("点火");
    }

    @Override
    public void hotPot() {
        System.out.println("热锅");
    }

    @Override
    public void pushOil() {
        System.out.println("放油");
    }

    @Override
    public void pushRawMaterial() {
        System.out.println("放原料排骨");
    }

    @Override
    public void Stir() {
        System.out.println("翻炒");
    }

    @Override
    public void pushSeasoning() {
        System.out.println("放调料,白砂糖,番茄酱、小苏打");
    }

    @Override
    public void outPot() {
        System.out.println("出锅");
    }

    @Override
    public void stirFry() {
        washingPot();
        onFire();
        hotPot();
        pushOil();
        pushRawMaterial();
        Stir();
        pushSeasoning();
        outPot();
    }

}

测试:

public class TestNoTemplate {
    public static void main(String[] args) {
        StirFry stirPork = new StirPork();
        stirPork.stirFry();
        System.out.println("====================================");
        StirFry stirSweetSourSpareribs = new StirSweetSourSpareribs();
        stirSweetSourSpareribs.stirFry();

    }
}

结果:虽然成功,但是会出现大量重复代码。
在这里插入图片描述

此时使用模板方法模式,使用一个抽象类来进行相同的复用,把不同的流给子类自己实现:
接口:

public interface StirFry {

    void washingPot();

    void onFire();

    void hotPot();

    void pushOil();

    void pushRawMaterial();

    void Stir();

    void pushSeasoning();

    void outPot();

    void stirFry();
}

抽象类:

public abstract class AbstractStirFry implements StirFry{

	///复写那些相同的方法已达到复用,然后不同的流给子类自己实现
    @Override
    public void washingPot() {
        System.out.println("洗锅");
    }

    @Override
    public void onFire() {
        System.out.println("点火");
    }

    @Override
    public void hotPot() {
        System.out.println("热锅");
    }

    @Override
    public void pushOil() {
        System.out.println("放油");
    }


    @Override
    public void Stir() {
        System.out.println("翻炒");
    }


    @Override
    public void outPot() {
        System.out.println("出锅");
    }

    @Override
    public void stirFry() {
        washingPot();
        onFire();
        hotPot();
        pushOil();
        pushRawMaterial();
        Stir();
        pushSeasoning();
        outPot();
    }
}

子类:

public class StirPork extends AbstractStirFry {


    @Override
    public void pushRawMaterial() {
        System.out.println("放原料猪肉");
    }


    @Override
    public void pushSeasoning() {
        System.out.println("放调料,盐,酱油");
    }


}

//甜酸排骨
//只需复写两个方法
public class StirSweetSourSpareribs extends AbstractStirFry {

    @Override
    public void pushRawMaterial() {
        System.out.println("放原料排骨");
    }


    @Override
    public void pushSeasoning() {
        System.out.println("放调料,白砂糖,番茄酱、小苏打");
    }


}


测试:

public class TestWithTemplate {
    public static void main(String[] args) {
        StirFry stirPork = new StirPork();
        stirPork.stirFry();
        System.out.println("====================================");
        StirFry stirSweetSourSpareribs = new StirSweetSourSpareribs();
        stirSweetSourSpareribs.stirFry();

    }
}

结果:
在这里插入图片描述
减少了大量重复模板代码。但是这种模式下,不太建议子类复写抽象类已经复写了的方法,尽可能遵循里氏替换原则。

模板方法优缺点:

优点:
1、利用模板方法将相同处理逻辑的代码放到抽象父类中,可以提高代码的复用性。
2、将不同的代码不同的子类中,通过对子类的扩展增加新的行为,提高代码的扩展性。
3、把不变的行为写在父类上,去除子类的重复代码,提供了一个很好的代码复用平台,
符合开闭原则。

缺点:
1、类数目的增加,每一个抽象类都需要一个子类来实现,这样导致类的个数增加。
2、类数量的增加,间接地增加了系统实现的复杂度。
3、继承关系自身缺点,如果父类添加新的抽象方法,所有子类都要改一遍。

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值