【设计模式】——模板方法模式(Template Method Pattern)

目录

引言

一、模板方法模式的基本概念

核心思想

模板方法模式的结构

UML图

应用场景

二、模板方法模式的优点与缺点

优点

缺点

三、C++实现模板方法模式

抽象类

具体子类

客户端代码

四、总结


引言

在软件开发中,设计模式是解决常见软件设计问题的一种系统化方法。模板方法模式(Template Method Pattern)是行为型设计模式的一种,它定义了一个算法的骨架,允许子类为一个或多个步骤提供具体实现。这种模式在不改变算法结构的前提下,通过重新定义算法的某些步骤,可以灵活地实现算法的多样化。

一、模板方法模式的基本概念

模板方法模式在一个抽象类中公开定义了执行算法的模板。这个模板包含了一个或多个基本方法,这些基本方法的具体实现由子类提供。通过这种模式,子类可以在不改变算法结构的情况下,通过重写基本方法来实现算法的不同部分。

核心思想

模板方法模式的核心在于定义一个算法的骨架,即模板方法。这个模板方法按照一定的顺序调用若干个基本方法,其中一些基本方法是抽象的,需要由子类实现;另外一些基本方法可以在抽象类中直接实现。

模板方法模式的结构

模板方法模式主要包含以下几个角色:

  • 抽象类(Abstract Class):定义了模板方法,这个方法中包含了算法的骨架,以及一个或多个抽象方法,这些抽象方法由子类实现。
  • 具体子类(Concrete Class):实现了抽象类中的抽象方法,从而完成算法中特定步骤的具体实现。

UML图

应用场景

模板方法模式适用于以下场景:

  1. 算法重用:当多个算法有共同的部分但在某些步骤上有所不同时,可以使用模板方法模式来重用共同部分的代码。
  2. 操作中的固定步骤:当某个操作包含多个固定步骤,但其中某些步骤的具体实现需要根据不同情况来变化时,可以使用模板方法模式。
  3. 扩展框架的功能:在框架设计中,可以使用模板方法模式来定义框架的核心流程,并允许用户通过继承来扩展框架的功能。
  4. 提供回调方法:在需要为特定事件或条件提供回调方法的场景中,模板方法模式可以非常有效。
  5. 遵循开闭原则:模板方法模式允许在不修改现有代码的情况下,通过扩展新的子类来增加新的行为,从而遵循开闭原则。

二、模板方法模式的优点与缺点

优点

  1. 代码复用:通过定义算法的骨架和固定步骤,模板方法模式允许在多个子类中重用这些代码,从而减少重复代码。
  2. 提高扩展性:通过允许子类实现算法的特定步骤,模板方法模式提供了足够的灵活性来适应不同的情境需求,同时不改变算法的整体结构。
  3. 遵循开闭原则:模板方法模式允许在不修改现有代码的情况下,通过扩展新的子类来增加新的行为,从而符合开闭原则。
  4. 提高可读性和可维护性:通过将复杂的算法分解为多个简单的步骤,并明确每个步骤的责任和功能,模板方法模式使得代码更加清晰和易于理解。同时,由于算法的实现被封装在模板类中,可以方便地进行维护和修改。

缺点

  1. 增加复杂性:随着子类的增加,系统的类数量也会增加,从而增加了系统的复杂性。同时,理解和维护这些类之间的继承关系也可能变得困难。
  2. 紧密耦合:模板方法模式通常意味着子类与抽象类之间的紧密耦合,这可能限制了子类的使用场景。
  3. 管理难度:随着子类数量的增加,管理和维护这些类变得更加困难。特别是当父类增加新的抽象方法时,所有的子类都需要进行修改以适应这些变化。
  4. 理解难度:对于新开发人员来说,理解整个框架的流程和扩展点可能比较困难,需要花费一定的时间来熟悉和学习。

三、C++实现模板方法模式

下面是一个使用C++实现的模板方法模式的示例。这个示例模拟了一个简单的咖啡冲泡过程,其中不同的咖啡(如美式咖啡和拿铁咖啡)共享冲泡的基本步骤,但在添加配料和煮咖啡的方式上有所不同。

抽象类

首先,我们定义一个抽象的Coffee类,它包含了冲泡咖啡的模板方法以及两个抽象方法(addIngredientsbrew),这些方法将由子类来实现。

#include <iostream>  
#include <string>  

class Coffee {
public:
    // 模板方法  
    void prepareRecipe() {
        boilWater();
        brew();
        pourInCup();
        if (wantsMilk()) {
            addMilk();
        }
        addIngredients();
    }

protected:
    // 钩子方法(可选)  
    virtual bool wantsMilk() {
        return false;
    }

    // 抽象方法  
    virtual void addIngredients() = 0;
    virtual void brew() = 0;

    // 具体方法  
    void boilWater() {
        std::cout << "Boiling water..." << std::endl;
    }

    void pourInCup() {
        std::cout << "Pouring into cup..." << std::endl;
    }

    void addMilk() {
        std::cout << "Adding milk..." << std::endl;
    }
};

具体子类

// 美式咖啡  
class Americano : public Coffee {
protected:
    void addIngredients() override {
        std::cout << "Adding Americano ingredients..." << std::endl;
    }

    void brew() override {
        std::cout << "Dripping Coffee through filter..." << std::endl;
    }
};

// 拿铁咖啡  
class Latte : public Coffee {
protected:
    bool wantsMilk() override {
        return true; // 拿铁咖啡需要牛奶  
    }

    void addIngredients() override {
        std::cout << "Adding espresso shots..." << std::endl;
        std::cout << "Adding flavorings..." << std::endl;
    }

    void brew() override {
        std::cout << "Brewing espresso..." << std::endl;
    }
};

客户端代码

// 客户端代码  
int main() {
    Americano americano;
    std::cout << "Making an Americano:" << std::endl;
    americano.prepareRecipe();

    Latte latte;
    std::cout << "\nMaking a Latte:" << std::endl;
    latte.prepareRecipe();

    return 0;
}

四、总结

模板方法模式通过定义一个算法的骨架,允许子类在不改变算法结构的前提下,通过重写某些步骤的具体实现来定制算法的行为。这种模式提高了代码的复用性和可维护性,使得算法的结构更加清晰,同时也便于扩展和维护。在C++中,模板方法模式是一种非常实用的设计模式,通过它我们可以构建出灵活且易于扩展的软件系统。

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值