Head First模版方法模式qt

本文详细介绍了模板方法设计模式,包括其定义、优点(如允许子类定制部分算法)、缺点(可能导致过多的子类)以及适用环境。通过CaffeineBeverage、Coffee和Tea类的代码示例,展示了如何实现模板方法模式,其中CaffeineBeverage作为抽象基类,定义了饮料制作的通用步骤,而Coffee和Tea类则实现了各自特有的酿造和添加调料的方法。此外,文章还提及了好莱坞原则在设计模式中的应用,强调了高层组件对底层组件的控制。

类图

在这里插入图片描述
在这里插入图片描述

定义

  • 定义一个操作中算法的骨架,而将这些步骤延迟到子类中,模板方法使得子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

优缺点

优点:

缺点:

适用环境:

  • 子类可以不改变一个算法的结构即可重新定义该算法的某些特定步骤。

设计原则

  • 好莱坞原则:别调用(打电话给)我们,我们会调用(打电话给)你。

  • 好莱坞原则可以防止“依赖腐败”。当高层组件依赖底层组件,底层组件又依赖高层组件,高层组件又依赖边侧组件,边侧组件又依赖高层组件…,依赖腐败就发生了。在这种情况下,没有人可以轻易搞懂系统是如何设计的。

  • 在好莱坞原则下,允许底层组件挂钩到系统上,但是高层组件会决定什么时候和怎样使用这些底层组件。即高层组件对底层组件的方式是:“别调用我们,我们会调用你”。
    在这里插入图片描述

代码

CaffeineBeverage类:

#ifndef CADDEINEBEVERAGE_H
#define CADDEINEBEVERAGE_H

#include <QDebug>

class CaffeineBeverage
{
public:
    void prepareRecipe();
    virtual void brew() = 0;
    virtual void addCondiments() = 0;
    void boilWater();
    void pourInCup();
    virtual bool customerWantsCondiments();
};

#endif // CADDEINEBEVERAGE_H

#include "caffeinebeverage.h"

void CaffeineBeverage::prepareRecipe()
{
    boilWater();
    brew();
    pourInCup();
    addCondiments();
}

void CaffeineBeverage::boilWater()
{
    qDebug() << "Boiling water";
}

void CaffeineBeverage::pourInCup()
{
    qDebug() << "Pouring into cup";
}

bool CaffeineBeverage::customerWantsCondiments()
{
    return true;
}

Coffee 类:

#ifndef COFFEE_H
#define COFFEE_H

#include "caffeinebeverage.h"

class Coffee : public CaffeineBeverage
{
public:
    void brew() override;
    void addCondiments() override;
    bool customerWantsCondiments() override;
};

#endif // COFFEE_H

#include "coffee.h"

void Coffee::brew()
{
    qDebug() << "Dripping Coffee through filter";
}

void Coffee::addCondiments()
{
    qDebug() << "Adding Sugar and Milk";
}

bool Coffee::customerWantsCondiments()
{
}

Tea类:

#ifndef TEA_H
#define TEA_H

#include "caffeinebeverage.h"

class Tea : public CaffeineBeverage
{
public:
    void brew() override;
    void addCondiments() override;
};

#endif // TEA_H

#include "tea.h"

void Tea::brew()
{
    qDebug() << "Steeping the Tea";
}

void Tea::addCondiments()
{
    qDebug() << "Adding Lemon";
}


测试:

#include "mainwindow.h"

#include "tea.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    Tea *myTea = new Tea();
    myTea->prepareRecipe();
}

MainWindow::~MainWindow()
{
}
05-29
### Qt 中 FIFO 的实现与使用 在 Qt 中,FIFO(First In First Out,先进先出)队列可以通过多种方式实现或使用。以下将从内置类支持和自定义实现两个方面进行详细说明。 #### 1. 使用 Qt 内置的 `QQueue` 类 Qt 提供了 `QQueue` 模板类来实现 FIFO 队列功能。`QQueue` 是一个动态数组,支持高效地在队列尾部添加元素和从队列头部移除元素。 - **添加元素**:可以使用 `enqueue()` 方法将元素添加到队列尾部。 - **移除元素**:可以使用 `dequeue()` 方法从队列头部移除元素。 - **访问队头元素**:可以使用 `head()` 方法获取队列头部的元素,但不会移除它。 以下是使用 `QQueue` 实现 FIFO 的代码示例: ```cpp #include <QQueue> #include <QString> void fifoExample() { QQueue<QString> queue; queue.enqueue("First"); // 添加元素到队列尾部 queue.enqueue("Second"); queue.enqueue("Third"); while (!queue.isEmpty()) { QString item = queue.dequeue(); // 从队列头部移除并获取元素 qDebug() << "Dequeued:" << item; } } ``` 上述代码展示了如何使用 `QQueue` 来管理 FIFO 队列[^1]。 #### 2. 自定义 FIFO 队列 如果需要更灵活的控制,可以基于 `QList` 或 `QVector` 自定义 FIFO 队列。例如,可以实现一个环形缓冲区(Circular Buffer),这是 FIFO 的一种常见实现方式。 以下是一个简单的环形缓冲区实现: ```cpp #include <QByteArray> #include <QDebug> class CircularBuffer { public: CircularBuffer(int size) : m_size(size), m_buffer(size, '\0'), m_head(0), m_tail(0), m_full(false) {} void push(char data) { if (isFull()) { qDebug() << "Buffer is full!"; return; } m_buffer[m_tail] = data; m_tail = (m_tail + 1) % m_size; if (m_tail == m_head) { m_full = true; } } char pop() { if (isEmpty()) { qDebug() << "Buffer is empty!"; return '\0'; } char data = m_buffer[m_head]; m_head = (m_head + 1) % m_size; m_full = false; return data; } bool isEmpty() const { return m_head == m_tail && !m_full; } bool isFull() const { return m_head == m_tail && m_full; } private: int m_size; QByteArray m_buffer; int m_head; int m_tail; bool m_full; }; void customFifoExample() { CircularBuffer buffer(5); buffer.push('A'); buffer.push('B'); buffer.push('C'); qDebug() << "Popped:" << buffer.pop(); // 输出 A qDebug() << "Popped:" << buffer.pop(); // 输出 B } ``` 上述代码展示了一个基于 `QByteArray` 的环形缓冲区实现[^2]。 #### 3. 结合定时器处理 FIFO 数据 在实际应用中,FIFO 常用于数据流的接收与解析。结合定时器,可以定期从 FIFO 队列中读取数据并进行处理。以下是一个示例: ```cpp #include <QTimer> #include <QByteArray> #include <QDebug> class Widget : public QObject { Q_OBJECT public: Widget(QObject *parent = nullptr) : QObject(parent) { QTimer *timer = new QTimer(this); connect(timer, &QTimer::timeout, this, &Widget::on_decodeTimer); timer->start(1); // 每 1ms 触发一次 } private slots: void on_decodeTimer() { static QByteArray buffer; static int len = 0; if (len > 0 && buffer[0] == 'S') { // 假设 STX 为 'S' QByteArray by = QByteArray(buffer.constData(), len); parseData(by); // 解析显示 buffer.remove(0, len); // 弹出数据 } else if (len > 0) { buffer.remove(0, 1); // 移除无效数据 } len = 0; // 重置长度 } private: void parseData(const QByteArray &data) { qDebug() << "Parsed Data:" << data; } }; ``` 上述代码展示了如何结合定时器定期从 FIFO 队列中读取数据并解析[^2]。 ### 总结 在 Qt 中,FIFO 的实现可以通过内置的 `QQueue` 类快速完成,也可以通过自定义环形缓冲区实现更灵活的功能。结合定时器可以实现数据流的实时处理与解析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值