c++模板模式

模板模式

什么是模板模式

模板模式(Template Method Pattern)是一种行为设计模式,它定义了一个操作中的算法骨架,将某些步骤的具体实现延迟到子类中。模板模式使得子类可以在不改变算法结构的情况下,重新定义算法的某些步骤,从而实现代码复用和扩展性。

使用场景包括:

存在一组相似的操作:当有一组操作拥有相同的算法结构,但是某些步骤的实现细节各不相同的时候,可以使用模板模式来定义这些操作的通用部分,并将变化的部分留给子类去实现。

算法结构固定,部分步骤可变:如果你希望在不改变算法整体结构的前提下,允许子类自由地扩展或修改某些步骤,模板模式是个很好的选择。这样可以保证算法的主体逻辑一致,同时提供必要的定制化能力。

封装算法细节:当需要将算法的实现细节封装起来,仅暴露一个高层接口给调用者使用时,模板模式可以帮助隐藏复杂的内部实现,提高代码的可读性和维护性。

代码复用和扩展:如果你发现有很多重复的代码,只是其中某些小部分逻辑不同,可以考虑使用模板模式提取公共部分到父类中,通过子类化来实现差异化的部分。

示例应用:

UI框架中的渲染流程,如所有页面都有加载、渲染内容、处理事件的基本流程,但具体的内容渲染逻辑由各个页面子类实现。
数据库访问框架中,可能有一个通用的数据库操作流程(连接数据库、发送查询、处理结果、关闭连接),而具体查询的SQL语句则由子类提供。
在框架或库的开发中,如Java并发包中的AbstractQueuedSynchronizer(AQS)使用模板方法模式定义了获取和释放锁的模板方法,具体实现留给子类(如ReentrantLock)。

为什么使用模板模式

在抽象类中统一操作步骤,并规定好接口,让子类实现接口。这样可以把各个具体的, 子类和操作步骤解耦合。你只希望客户端扩展某个特定算法步骤,而不是整个算法或其结构时,可使用模板方法模式。当多个类的算法除一些细微不同之外几乎完全一样时, 你可使用该模式。但其后果就是,只要算法发生变化, 你就可能需要修改所有的类。

模板模式实现步骤

1.提供一个抽象类:负责规定好接口,让子类实现接口,定义一个模板方法

2.提供具体实现子类:实现抽象类的抽象接口即可
在这里插入图片描述

示例

#include <iostream>

// 抽象基类,定义模板方法和基本操作
class CoffeeMaker {
public:
    virtual ~CoffeeMaker() {}
    // 模板方法:冲泡咖啡的步骤
    void brewCoffee() {
        boilWater();
        brew();
        pourInCup();
        if (customerWantsCondiments()) {
            addCondiments();
        }
    }

protected:
    // 基本操作,留给子类实现
    virtual void brew() = 0;
    virtual void addCondiments() = 0;

    // 可能不需要子类重写的辅助方法
    void boilWater() {
        std::cout << "Boiling water" << std::endl;
    }
    void pourInCup() {
        std::cout << "Pouring into cup" << std::endl;
    }

    // 可能需要子类决定的策略方法
    virtual bool customerWantsCondiments() {
        return true;
    }
};

// 具体子类:黑咖啡
class BlackCoffee : public CoffeeMaker {
protected:
    void brew() override {
        std::cout << "Brewing black coffee" << std::endl;
    }
    void addCondiments() override {
        // 黑咖啡不加调料
    }
};

// 具体子类:加糖加奶咖啡
class SugarMilkCoffee : public CoffeeMaker {
protected:
    void brew() override {
        std::cout << "Brewing coffee with sugar and milk" << std::endl;
    }
    void addCondiments() override {
        std::cout << "Adding sugar and milk" << std::endl;
    }
    bool customerWantsCondiments() override {
        return true;
    }
};

int main() {
    CoffeeMaker* maker = new BlackCoffee();
    maker->brewCoffee();
    delete maker;

    std::cout << "\n";

    maker = new SugarMilkCoffee();
    maker->brewCoffee();
    delete maker;

    return 0;
}

在这个例子中,CoffeeMaker类是抽象基类,它定义了冲泡咖啡的基本步骤作为模板方法(brewCoffee),并声明了两个纯虚函数brew和addCondiments作为基本操作,让子类去实现。BlackCoffee和SugarMilkCoffee是具体子类,它们实现了不同的冲泡方式和添加调料的逻辑。通过这种方式,我们可以复用通用的冲泡流程,同时允许子类灵活地改变某些步骤,符合模板方法模式的设计理念。

模板模式优缺点

优点

  • 你可仅允许客户端重写一个大型算法中的特定部分, 使得算法其他部分修改对其所造成的影响减小
  • 你可将重复代码提取到一个超类中

缺点

  • 部分客户端可能会受到算法框架的限制
  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则
  • 模板方法中的步骤越多, 其维护工作就可能会越困难

相关推荐

  1. c#模板设计模式

    2024-06-17 08:46:01       30 阅读
  2. c++ 设计模式模版方法

    2024-06-17 08:46:01       17 阅读
  3. 模版模式(极简c++)》

    2024-06-17 08:46:01       11 阅读
  4. C++中的模板方法模式

    2024-06-17 08:46:01       5 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-17 08:46:01       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-17 08:46:01       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-17 08:46:01       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-17 08:46:01       18 阅读

热门阅读

  1. SpringSecurity(JWT、SecurityConfig、Redis)

    2024-06-17 08:46:01       6 阅读
  2. API 类别 - 特效核心

    2024-06-17 08:46:01       5 阅读
  3. Linux 基础IO 三

    2024-06-17 08:46:01       6 阅读
  4. 你应该知道的口语连读技巧

    2024-06-17 08:46:01       6 阅读
  5. Rust创建基准测试bench

    2024-06-17 08:46:01       6 阅读
  6. AWS无服务器 应用程序开发—第十三章 小结2

    2024-06-17 08:46:01       5 阅读
  7. 迁移学习和从头训练(from scratch)的区别

    2024-06-17 08:46:01       6 阅读
  8. Conda编译

    2024-06-17 08:46:01       8 阅读
  9. Linux 常用命令 - userdel 【删除用户】

    2024-06-17 08:46:01       7 阅读
  10. SQL COUNT() 函数深入解析

    2024-06-17 08:46:01       5 阅读
  11. MySQL入门学习-子查询.ALL

    2024-06-17 08:46:01       8 阅读
  12. 快速排序压缩算法2024年最新一种压缩算法

    2024-06-17 08:46:01       7 阅读
  13. 第66集《摄大乘论》

    2024-06-17 08:46:01       7 阅读