Head First外观模式qt

这篇博客介绍了外观模式在复杂家庭影院系统中的实现,通过`HomeTheaterFacade`类作为统一接口,简化了对各个子系统(如放大器、DVD播放器等)的操作。文章展示了如何通过外观模式降低系统复杂性,提高客户代码的易用性,并提供了相关类的定义和测试用例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

类图

在这里插入图片描述

在这里插入图片描述

定义

  • 提供一个统一的接口去访问多个子系统的多个不同的接口。

  • 定义了一个高层次的接口,使得子系统更容易被使用。

优缺点

优点:

  • 提供了一个简单且公用的接口去处理复杂的子系统,并且没有子系统的功能。

  • 遮蔽了子系统的复杂性,避免了客户与子系统直接连接,也减少了子系统与子系统间的连接,每个子系统都有它的Facade模式,子系统Facade模式去访问其他子系统。

缺点

  • 限制了客户的自由,减少了可变性。

适用环境:

  • 需要复杂的子系统提供一个简单的接口。
  • 客户与抽象的实现类中存在若干依赖。
  • 子系统分层是必要的或架构要求的情况下

设计原则

  • 最少知识原则:只和你的密友谈话

代码

HomeTheaterFacade类:

#ifndef HOMETHEATERFACADE_H
#define HOMETHEATERFACADE_H

#include "amplifier.h"
#include "tuner.h"
#include "dvdplayer.h"
#include "cdplayer.h"
#include "projector.h"
#include "theaterlights.h"
#include "screen.h"
#include "popcornpopper.h"

#include <QString>

class HomeTheaterFacade
{
public:
    HomeTheaterFacade(Amplifier *amp,
    Tuner *tuner,
    DvdPlayer *dvd,
    CdPlayer *cd,
    Projector *projector,
    TheaterLights *lights,
    Screen *screen,
    PopcornPopper *popper);
    void watchMovie(QString movie);
    void endMovie();

private:
    Amplifier *amp;
    Tuner *tuner;
    DvdPlayer *dvd;
    CdPlayer *cd;
    Projector *projector;
    TheaterLights *lights;
    Screen *screen;
    PopcornPopper *popper;
};

#endif // HOMETHEATERFACADE_H

#include "hometheaterfacade.h"

HomeTheaterFacade::HomeTheaterFacade(Amplifier *amp,
                                     Tuner *tuner,
                                     DvdPlayer *dvd,
                                     CdPlayer *cd,
                                     Projector *projector,
                                     TheaterLights *lights,
                                     Screen *screen,
                                     PopcornPopper *popper)
{
    this->amp = amp;
    this->tuner = tuner;
    this->dvd = dvd;
    this->cd = cd;
    this->projector = projector;
    this->lights = lights;
    this->screen =screen;
    this->popper = popper;
}

void HomeTheaterFacade::watchMovie(QString movie)
{
    qDebug() << "Get ready to watch a movie....";
    popper->on();
    popper->pop();
    lights->dim(10);
    screen->down();
    projector->on();
    projector->wideScreenMode();
    amp->on();
    amp->setDvd(dvd);
    amp->setSurroundSound();
    amp->setVolume(5);
    dvd->on();
    dvd->play(movie);
}

void HomeTheaterFacade::endMovie()
{
    qDebug() << "Shutting movie theater down...";
    popper->off();
    lights->on();
    screen->up();
    projector->off();
    amp->off();
    dvd->stop();
    dvd->eject();
    dvd->off();
}

Amplifier类:

#ifndef AMPLIFIER_H
#define AMPLIFIER_H

#include "dvdplayer.h"

class Amplifier
{
public:
    Amplifier();
    void on();
    void off();
    void setDvd(DvdPlayer *dvd);
    void setSurroundSound();
    void setVolume(int volume);
};

#endif // AMPLIFIER_H

#include "amplifier.h"

Amplifier::Amplifier()
{

}

void Amplifier::on()
{
    qDebug() << "Top-O-Line Amplifier on";
}

void Amplifier::off()
{
    qDebug() << "Top-O-Line Amplifier off";
}

void Amplifier::setDvd(DvdPlayer *dvd)
{
    qDebug() << "Top-O-Line Amplifier setting "
             << "DVD player to Top-O-Line DVD player";
}

void Amplifier::setSurroundSound()
{

}

void Amplifier::setVolume(int volume)
{
    qDebug() << "Top-O-Line Amplifier setting volume to "
             << QString::number(volume);
}

CdPlayer类:

#ifndef CDPLAYER_H
#define CDPLAYER_H


class CdPlayer
{
public:
    CdPlayer();
};

#endif // CDPLAYER_H

#include "cdplayer.h"

CdPlayer::CdPlayer()
{

}

DvdPlayer类:

#ifndef DVDPLAYER_H
#define DVDPLAYER_H

#include <QDebug>
#include <QString>

class DvdPlayer
{
public:
    DvdPlayer();
    void on();
    void play(QString movie);
    void stop();
    void eject();
    void off();

private:
    QString movie;
};

#endif // DVDPLAYER_H

#include "dvdplayer.h"

DvdPlayer::DvdPlayer()
{

}

void DvdPlayer::on()
{
    qDebug() << "Top-O-Line DVD Player on";
}

void DvdPlayer::play(QString movie)
{
    qDebug() << "Top-O-Line DVD Player playing "
             << movie;
    this->movie = movie;
}

void DvdPlayer::stop()
{
    qDebug() << "Top-O-Line DVD Player stopped "
             << movie;
}

void DvdPlayer::eject()
{
    qDebug() << "Top-O-Line DVD Player eject";
}

void DvdPlayer::off()
{
    qDebug() << "Top-O-Line DVD Player off";
}

PopcornPopper类:

#ifndef POPCORNPOPPER_H
#define POPCORNPOPPER_H

#include <QDebug>

class PopcornPopper
{
public:
    PopcornPopper();
    void on();
    void off();
    void pop();
};

#endif // POPCORNPOPPER_H

#include "popcornpopper.h"

PopcornPopper::PopcornPopper()
{

}

void PopcornPopper::on()
{
    qDebug() << "Popcorn Popper on";
}

void PopcornPopper::off()
{
    qDebug() << "Popcorn Popper off";
}

void PopcornPopper::pop()
{
    qDebug() << "Popcorn Popper popping popcorn!";
}

Projector类:

#ifndef PROJECTOR_H
#define PROJECTOR_H


class Projector
{
public:
    Projector();
    void on();
    void off();
    void wideScreenMode();
};

#endif // PROJECTOR_H

#include "projector.h"

#include <QDebug>

Projector::Projector()
{

}

void Projector::on()
{
    qDebug() << "Top-O-Line Projector on";
}

void Projector::off()
{
    qDebug() << "Top-O-Line Projector off";
}

void Projector::wideScreenMode()
{
    qDebug() << "Top-O-Line Projector in wideScreenMode (16*9 aspect ratio)";
}

Screen类:

#ifndef SCREEN_H
#define SCREEN_H

#include <QDebug>

class Screen
{
public:
    Screen();
    void up();
    void down();
};

#endif // SCREEN_H

#include "screen.h"

Screen::Screen()
{

}

void Screen::up()
{
    qDebug() << "Theater Screen going up";
}

void Screen::down()
{
    qDebug() << "Theater Screen going down";
}

TheaterLights类:

#ifndef THEATERLIGHTS_H
#define THEATERLIGHTS_H


class TheaterLights
{
public:
    TheaterLights();
    void on();
    void dim(int value);

};

#endif // THEATERLIGHTS_H

#include "theaterlights.h"

#include <QDebug>

TheaterLights::TheaterLights()
{

}

void TheaterLights::on()
{
    qDebug() << "Theater Ceiling Lights on";

}

void TheaterLights::dim(int value)
{
    qDebug() << "Theater Ceiling Lights dimming to" << QString::number(value) << "%";
}

Tuner类:

#ifndef TUNER_H
#define TUNER_H


class Tuner
{
public:
    Tuner();
};

#endif // TUNER_H

#include "tuner.h"

Tuner::Tuner()
{

}

测试:

#include "mainwindow.h"
#include "hometheaterfacade.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
    Amplifier *amp = new Amplifier();
    Tuner *tuner = new Tuner();
    DvdPlayer *dvd = new DvdPlayer();
    CdPlayer *cd = new CdPlayer();
    Projector *projector = new Projector();
    Screen *screen = new Screen();
    TheaterLights *lights = new TheaterLights();
    PopcornPopper *popper = new PopcornPopper();

    HomeTheaterFacade *homeTheater
            = new HomeTheaterFacade(amp, tuner, dvd, cd,
                                    projector, lights, screen,popper);
    homeTheater->watchMovie("Raiders of the Lost Ark");
    homeTheater->endMovie();
}

MainWindow::~MainWindow()
{
}


### 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` 类快速完成,也可以通过自定义环形缓冲区实现更灵活的功能。结合定时器可以实现数据流的实时处理与解析。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值