设计模式系列(行为型模式)之一 模板方法模式

模板方法模式

模板方法模式定义了一个流程的骨架,由多个方法组成。并允许子类为一个或多个步骤提供实现。简而言之就是公共的不变的部分由父类统一实现,变化的部分由子类来个性化实现。

优点:
提高复用性;
提高拓展性;
符合开闭原则。

缺点:
类的数目增加;
增加了系统实现的复杂度;
父类添加新的抽象方法,所有子类都要改一遍。

模板方法模式包含以下主要角色。
抽象类(Abstract Class):负责给出一个算法的轮廓和骨架。它由一个模板方法和若干个基本方法构成。这些方法的定义如下。
模板方法:定义了算法的骨架,按某种顺序调用其包含的基本方法。
基本方法:是整个算法中的一个步骤,包含以下几种类型:
抽象方法:在抽象类中申明,由具体子类实现。
具体方法:在抽象类中已经实现,在具体子类中可以继承或重写它。
钩子方法:在抽象类中已经实现,包括用于判断的逻辑方法和需要子类重写的空方法两种。
具体子类(Concrete Class):实现抽象类中所定义的抽象方法和钩子方法,它们是一个顶级逻辑的一个组成步骤。

模板方法模式通常适用于以下场景:
1.算法的整体步骤很固定,但其中个别部分易变时,这时候可以使用模板方法模式,将容易变的部分抽象出来,供子类实现。
2.当多个子类存在公共的行为时,可以将其提取出来并集中到一个公共父类中以避免代码重复。首先,要识别现有代码中的不同之处,并且将不同之处分离为新的操作。最后,用一个调用这些新的操作的模板方法来替换这些不同的代码。
3.当需要控制子类的扩展时,模板方法只在特定点调用钩子操作,这样就只允许在这些点进行扩展。

1.定义一个网上购买外卖的抽象类,里面有支付,下单,制作,配送等主要流程,
其中下单和打包配送行为是固定的,不同的是制作和支付过程,所以order和send方法提供了默认实现,并且由final修饰,子类不可重写。另外我们还可以通过needOther这个钩子方法来控制某些子类的定制化需求。

public abstract class Buy {
    
    
    protected abstract void pay();
    final void order(){
    
    
        System.out.println("下单成功了");
    };
    protected abstract void make();

    final void send(){
    
    
        System.out.println("打包配送");
    };
    protected boolean needOther(){
    
    
        return true;
    };
    final void flow(){
    
    
        this.pay();
        this.order();
        this.make();
        if(needOther()){
    
    
            System.out.println("需要餐具");
        }
        this.send();
    }
}

2.创建一个购买蛋糕类,继承自购买抽象类,由于需要餐具,所以加了needOther

public class BuyCake extends Buy{
    
    
    private final boolean needOther;

    public BuyCake(boolean needOther) {
    
    
        this.needOther = needOther;
    }

    @Override
    protected void pay() {
    
    
        System.out.println("我支付了30元");
    }

    @Override
    protected void make() {
    
    
        System.out.println("制作蛋糕了");
    }

    @Override
    protected boolean needOther() {
    
    
        return super.needOther();
    }
}

3.创建一个购买水果类,继承自购买抽象类,不需要餐具,可以直接重写needOther返回false,也可以跟上面一样加个needOther属性

public class BuyFruit extends Buy {
    
    
    @Override
    protected void pay() {
    
    
        System.out.println("我支付了20元");
    }

    @Override
    protected void make() {
    
    
        System.out.println("挑选包装了");
    }

    @Override
    protected boolean needOther() {
    
    
        return false;
    }
}

4.测试输出

public class Test {
    
    
    public static void main(String[]args){
    
    
        BuyCake buyCake=new BuyCake(true);
        buyCake.flow();
        System.out.println("-----------------------");
        BuyFruit buyFruit=new BuyFruit();
        buyFruit.flow();
    }
}
我支付了30元
下单成功了
制作蛋糕了
需要餐具
打包配送
-----------------------
我支付了20元
下单成功了
挑选包装了
打包配送

模板方法模式需要注意抽象类与具体子类之间的协作。它用到了函数的多态性技术以及“不用调用我,让我来调用你”的反向控制技术,下一篇讲讲迭代器模式

猜你喜欢

转载自blog.csdn.net/qq_40136782/article/details/108335150