c++模板模式

文章目录

模板模式

什么是模板模式

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

使用场景包括:

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

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

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

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

示例应用:

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

为什么使用模板模式

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

模板模式实现步骤

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

2.提供具体实现子类:实现抽象类的抽象接口即可

示例

cpp 复制代码
#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是具体子类,它们实现了不同的冲泡方式和添加调料的逻辑。通过这种方式,我们可以复用通用的冲泡流程,同时允许子类灵活地改变某些步骤,符合模板方法模式的设计理念。

模板模式优缺点

优点

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

缺点

  • 部分客户端可能会受到算法框架的限制
  • 通过子类抑制默认步骤实现可能会导致违反里氏替换原则
  • 模板方法中的步骤越多, 其维护工作就可能会越困难
相关推荐
武昌库里写JAVA1 分钟前
Java成长之路(一)--SpringBoot基础学习--SpringBoot代码测试
java·开发语言·spring boot·学习·课程设计
CYBEREXP200818 分钟前
MacOS M3源代码编译Qt6.8.1
c++·qt·macos
ZSYP-S37 分钟前
Day 15:Spring 框架基础
java·开发语言·数据结构·后端·spring
yuanbenshidiaos40 分钟前
c++------------------函数
开发语言·c++
yuanbenshidiaos44 分钟前
C++----------函数的调用机制
java·c++·算法
程序员_三木1 小时前
Three.js入门-Raycaster鼠标拾取详解与应用
开发语言·javascript·计算机外设·webgl·three.js
是小崔啊1 小时前
开源轮子 - EasyExcel01(核心api)
java·开发语言·开源·excel·阿里巴巴
tianmu_sama1 小时前
[Effective C++]条款38-39 复合和private继承
开发语言·c++
黄公子学安全1 小时前
Java的基础概念(一)
java·开发语言·python
liwulin05061 小时前
【JAVA】Tesseract-OCR截图屏幕指定区域识别0.4.2
java·开发语言·ocr