C++设计模式之 模板方法模式

【声明】本题目来源于卡码网(题目页面 (kamacoder.com))

【提示:如果不想看文字介绍,可以直接跳转到C++编码部分】


【设计模式大纲】


【简介】

        --什么是模板方法模式(第18种设计模式)

        模板方法模式(Template Method Pattern)是⼀种行为型设计模式, 它定义了⼀个算法的骨架,将⼀些步骤的实现延迟到⼦类。模板方法模式使得⼦类可以在不改变算法结构的情况下,重新定义算法中的某些步骤。

        举个简单的例⼦,做⼀道菜通常都需要包含⾄少三步:

  • 准备⻝材
  • 亨饪过程
  • 上菜

        不同菜品的亨饪过程是不⼀样的,但是我们可以先定义⼀个”⻣架”,包含这三个步骤,亨饪过程的过程放到具体的炒菜类中去实现,这样,⽆论炒什么菜,都可以沿⽤相同的炒菜算法,只需在⼦类中实现具体的炒菜步骤,从而提⾼了代码的复⽤性。


【基本结构】

        模板⽅法模式的基本结构包含以下两个角色:

  • 模板类AbstractClass :由⼀个模板⽅法和若⼲个基本⽅法构成,模板⽅法定义了逻辑的⻣架,按照顺序调⽤包含的基本⽅法,基本⽅法通常是⼀些抽象⽅法,这些⽅法由⼦类去实现。基本⽅法还包含⼀些具体⽅法,它们是算法的⼀部分但已经有默认实现,在具体⼦类中可以继承或者重写。
  • 具体类ConcreteClass :继承⾃模板类,实现了在模板类中定义的抽象⽅法,以完成算法中特定步骤的具体实现。

【简易实现】

        模板⽅法模式的简单示例如下:先以Java代码作以说明

1. 定义模板类,包含模板⽅法,定义了算法的⻣架, ⼀般都加上final 关键字C++为 const关键字),避免子类重写。

// 模板类
abstract class AbstractClass {
    // 模板⽅法,定义了算法的⻣架
    public final void templateMethod() {
        step1();
        step2();
        step3();
    }
    // 抽象⽅法,由⼦类实现
    protected abstract void step1();
    protected abstract void step2();
    protected abstract void step3();
}

2. 定义具体类, 实现模板类中的抽象⽅法

// 具体类
class ConcreteClass extends AbstractClass {
    @Override
    protected void step1() {
        System.out.println("Step 1 ");
    }
    @Override
    protected void step2() {
        System.out.println("Step 2 ");
    }
    @Override
    protected void step3() {
        System.out.println("Step 3");
    }
}

3. 客户端实现

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/

public class Main {
    public static void main(String[] args) {
        AbstractClass concreteTemplate = new ConcreteClass();
        // 触发整个算法的执⾏
        concreteTemplate.templateMethod();
    }
}

【应用场景】

        模板⽅法模式将算法的不变部分被封装在模板⽅法中,而可变部分算法由⼦类继承实现,这样做可以很好的提⾼代码的复⽤性,但是当算法的框架发⽣变化时,可能需要修改模板类,这也会影响到所有的⼦类。
        总体来说,当算法的整体步骤很固定,但是个别步骤在更详细的层次上的实现可能不同时,通常考虑模板⽅法模式来处理。在已有的⼯具和库中, Spring框架中的JdbcTemplate 类使⽤了模板⽅法模式,其中定义了⼀些执⾏数据库操作的模板⽅法,具体的数据库操作由回调函数提供。⽽在Java的JDK源码中, AbstractList 类也使⽤了模板⽅法模式,它提供了⼀些通用的⽅法,其中包括⼀些模板⽅法。具体的列表操作由⼦类实现。


【C++编码部分】

1. 题目描述

        小明喜欢品尝不同类型的咖啡,她发现每种咖啡的制作过程有一些相同的步骤,他决定设计一个简单的咖啡制作系统,使用模板方法模式定义咖啡的制作过程。系统支持两种咖啡类型:美式咖啡(American Coffee)和拿铁(Latte)。

        咖啡制作过程包括以下步骤:

        1. 研磨咖啡豆 Grinding coffee beans

        2. 冲泡咖啡 Brewing coffee

        3. 添加调料 Adding condiments

        其中,美式咖啡和拿铁的调料添加方式略有不同, 拿铁在添加调料时需要添加牛奶Adding milk。

2. 输入描述

        多行输入,每行包含一个数字,表示咖啡的选择(1 表示美式咖啡,2 表示拿铁)。

3. 输出描述

        根据每行输入,输出制作咖啡的过程,包括咖啡类型和各个制作步骤,末尾有一个空行。

4. C++编码实例

/**
* @version Copyright (c) 2024 NCDC, Servo。 Unpublished - All rights reserved
* @file TemplateMethodMode.hpp
* @brief 模板方法模式
* @autor 写代码的小恐龙er
* @date 2024/01/20
*/

#include <iostream>
#include <string>
#include <vector>

using namespace std;

// 前置声明

// 抽象模板类 -- 包含模板⽅法,定义了算法的⻣架, ⼀般都加上final 关键字,避免⼦类重写
class CoffeeMaker;
// 实现具体类 -- 美式
class AmericanCoffeeMaker;
// 实现具体类 -- 拿铁
class LatteCoffeeMaker;

// 类的定义

// 抽象模板类
class CoffeeMaker
{
// 成员接口函数
public:
    // 框架接口函数
    const void TemplateCoffeeMethod(){
        // 步骤一
        GrindingCoffeeBeans();
        // 步骤二
        BrewingCoffee();
        // 步骤三
        AddingCondiments();
        // 空行
        std::cout << endl;
    }
    // 研磨咖啡豆工序
    virtual void GrindingCoffeeBeans() = 0;
    // 冲泡咖啡工序
    virtual void BrewingCoffee() = 0;
    // 添加调料工序
    virtual void AddingCondiments(){
        std::cout << "Adding condiments" << endl;
    }
};

// 实现具体类 -- 美式
class AmericanCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
    string _coffeeName;

// 成员接口函数重载
public:
    // 构造函数
    AmericanCoffeeMaker(string name){
        this->_coffeeName = name;
        std::cout<< "Making " << _coffeeName << ":"<<endl;
    }
    // 研磨咖啡豆工序 重载
    void GrindingCoffeeBeans() override {
        std::cout << "Grinding coffee beans" << endl;
    }
    // 冲泡咖啡工序 重载
    void BrewingCoffee() override {
        std::cout << "Brewing coffee" << endl;
    }
};

// 实现具体类 -- 拿铁
class LatteCoffeeMaker : public CoffeeMaker
{
// 成员数据
private:
    string _coffeeName;

// 成员接口函数重载
public:
    // 构造函数
    LatteCoffeeMaker(string name){
        this->_coffeeName = name;
        std::cout<< "Making " << _coffeeName << ":"<<endl;
    }
    // 研磨咖啡豆工序 重载
    void GrindingCoffeeBeans() override {
        std::cout << "Grinding coffee beans" << endl;
    }
    // 冲泡咖啡工序 重载
    void BrewingCoffee() override {
        std::cout << "Brewing coffee" << endl;
    }
    // 添加调料工序 重载
    void AddingCondiments() override {
        std::cout << "Adding milk" << endl;
        std::cout << "Adding condiments" << endl;
    }
};


// 客户端代码
int main()
{
    // 输入的咖啡制作类型
    int type = 0;
    // 构造抽象模板类
    CoffeeMaker *coffee = nullptr;
    while(std::cin >> type){
        if(type == 1){
            coffee = new AmericanCoffeeMaker("American Coffee");
        }
        else if(type == 2){
            coffee = new LatteCoffeeMaker("Latte");
        }
        else break;
        
        // 开始统一制作咖啡
        coffee->TemplateCoffeeMethod();
    }
    
    // 析构
    if(coffee != nullptr){
        delete coffee;
        coffee = nullptr;
    }
    
    return 0;
}



......

To be continued.

  • 28
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
模板方法设计模式是一种行为设计模式,它定义了一个算法的骨架,将一些步骤的实现延迟到子类中。这种模式可以确保算法的结构保持不变,但允许子类提供特定的实现细节。在C++中,模板方法设计模式可以通过使用虚函数和继承来实现。 在给出的引用中,我们可以看到一个名为CoffeineBeverage的类,它定义了一个prepare_recipe()方法,并在内部调用了其他几个私有方法。这个类是一个基类,可以被子类继承并重写其中的方法。 具体来说,模板方法设计模式的关键是将算法的骨架定义在基类中,而将可变的实现细节留给子类去实现。在这个例子中,prepare_recipe()方法是算法的骨架,而brew()和add_condiments()方法则是可变的实现细节。 通过将brew()和add_condiments()方法定义为虚函数,基类CoffeineBeverage允许子类去重写这些方法以提供自己的实现。这样,当调用prepare_recipe()方法时,实际执行的是子类中重写后的方法。 使用模板方法设计模式的好处是可以提高代码的复用性和可扩展性。算法的骨架在基类中只需要定义一次,而具体的实现细节可以在不同的子类中灵活变化。 总结起来,C++中的模板方法设计模式通过定义一个算法的骨架并将可变的实现细节留给子类去实现,可以提供代码的复用性和可扩展性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [C++设计模式模板方法模式](https://blog.csdn.net/Long_xu/article/details/127118813)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [C++设计模式-模板方法模式](https://blog.csdn.net/qq78442761/article/details/91990149)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

写代码的小恐龙er

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值