c++面试11_什么是高内聚低耦合

🧩 一、核心概念

概念含义理想状态
内聚(Cohesion)模块内部功能之间的关联程度一个模块只做一类事情(单一职责
耦合(Coupling)模块之间的依赖程度模块之间相互独立,接口清晰、依赖最小

简言之:

高内聚 → 模块内部紧密合作
低耦合 → 模块之间松散关联

⚙️ 二、设计原则(必须掌握)

  1. 单一职责原则 (SRP)
    每个模块或类只负责一项功能。

    • ✅ 好:Logger 只负责日志,不负责打印格式。

    • ❌ 坏:一个 Utils 里什么工具函数都有。

  2. 开闭原则 (OCP)
    对扩展开放,对修改关闭。
    → 使用接口、多态、配置等方式扩展功能,而不是改老代码。

  3. 依赖倒置原则 (DIP)
    高层模块不依赖低层模块,两者都依赖抽象。
    → 用接口代替具体实现。

  4. 接口隔离原则 (ISP)
    一个接口不应该被强迫依赖它不使用的方法。
    → 小接口更容易复用。

  5. 迪米特法则(最少知道原则)
    模块之间尽量少打交道,只与直接朋友通信。
    → 减少隐性依赖。

  6. 🔨 三、实现高内聚低耦合的常用方法

技术/方法说明
模块化设计将系统按功能拆分成独立模块(UI、逻辑、数据层)
分层架构典型如 MVC / MVP / MVVM,让各层职责单一
接口 + 抽象类使用抽象接口作为模块边界,隐藏实现细节
依赖注入(DI)把依赖关系交给外部容器或构造函数注入
事件/回调机制模块之间通过事件或信号槽通信,而不是直接调用
设计模式应用观察者、策略、工厂、适配器等都可降低耦合

🧠 四、示例(以 C++ 为例)

❌ 坏例(高耦合、低内聚)

class OrderProcessor {
public:
    void process() {
        // 订单逻辑
        // 直接调用数据库操作
        DBConnection db;
        db.connect();
        db.saveOrder(this);
        
        // 直接打印日志
        std::cout << "Order processed!" << std::endl;
    }
};

好例(高内聚、低耦合)

class ILogger {
public:
    virtual void log(const std::string& msg) = 0;
    virtual ~ILogger() = default;
};

class IOrderRepository {
public:
    virtual void save(const Order& order) = 0;
    virtual ~IOrderRepository() = default;
};

class OrderProcessor {
    IOrderRepository& repo;
    ILogger& logger;
public:
    OrderProcessor(IOrderRepository& r, ILogger& l) : repo(r), logger(l) {}
    void process(const Order& order) {
        repo.save(order);
        logger.log("Order processed");
    }
};

特点:

  • 高内聚OrderProcessor 只负责订单处理。

  • 低耦合:通过接口依赖,数据库或日志实现可自由替换(例如文件日志、远程日志)。

  • 符合依赖倒置:依赖抽象而非具体实现。

🧭 五、总结口诀

模块内:功能要聚焦(高内聚)
模块间:接口要解耦(低耦合)

或者更口语化一点:

“各司其职、相互独立、通过契约沟通、不要硬绑在一起。”

🎯 目标场景

我们要设计一个典型的 Qt 上位机程序,它包含以下模块:

  • UI层:显示测试状态、用户操作按钮

  • 业务逻辑层:控制测试流程(开始、停止、结果分析)

  • 通信层:负责与硬件(比如测试机)通信

  • 日志层:负责系统日志记录

  • 🧩 一、结构设计(模块划分)

App
 ├── main.cpp
 ├── ui/
 │    └── MainWindow.h / .cpp
 ├── core/
 │    ├── TestController.h / .cpp   ← 业务逻辑层(高内聚)
 │    └── ICommInterface.h          ← 通信接口抽象(低耦合)
 ├── comm/
 │    ├── SerialComm.h / .cpp       ← 串口实现
 │    └── PcieComm.h / .cpp         ← PCIe 实现
 ├── log/
 │    └── Logger.h / .cpp

⚙️ 二、接口与实现(低耦合)

通信层接口抽象(ICommInterface.h)

#pragma once
#include <QObject>
#include <QByteArray>

class ICommInterface : public QObject {
    Q_OBJECT
public:
    explicit ICommInterface(QObject* parent = nullptr) : QObject(parent) {}
    virtual ~ICommInterface() = default;

    virtual bool connectDevice() = 0;
    virtual void disconnectDevice() = 0;
    virtual bool sendCommand(const QByteArray& data) = 0;

signals:
    void dataReceived(const QByteArray& data);
};
串口通信实现(SerialComm.h/.cpp)

#pragma once
#include "ICommInterface.h"
#include <QSerialPort>

class SerialComm : public ICommInterface {
    Q_OBJECT
    QSerialPort port;
public:
    bool connectDevice() override {
        port.setPortName("COM3");
        return port.open(QIODevice::ReadWrite);
    }

    void disconnectDevice() override {
        port.close();
    }

    bool sendCommand(const QByteArray& data) override {
        return port.write(data) == data.size();
    }

private slots:
    void onReadyRead() {
        emit dataReceived(port.readAll());
    }
};
✅ 通过接口实现隔离。
程序上层只依赖 ICommInterface,完全不关心底层是串口、USB 还是 PCIe

🔧 三、业务逻辑层(高内聚)

#pragma once
#include <QObject>
#include "ICommInterface.h"
#include "Logger.h"

class TestController : public QObject {
    Q_OBJECT
    ICommInterface* comm;
    Logger* logger;

public:
    TestController(ICommInterface* c, Logger* l, QObject* parent = nullptr)
        : QObject(parent), comm(c), logger(l) 
    {
        connect(comm, &ICommInterface::dataReceived, this, &TestController::onDataReceived);
    }

public slots:
    void startTest() {
        logger->log("Test started");
        comm->sendCommand("START");
    }

    void stopTest() {
        logger->log("Test stopped");
        comm->sendCommand("STOP");
    }

private slots:
    void onDataReceived(const QByteArray& data) {
        logger->log("Data received: " + QString(data));
    }
};
};
✅ TestController 只负责“测试业务逻辑”,
不关心通信是怎么实现的,也不直接操作UI。

四、UI层(信号槽解耦)

#pragma once
#include <QMainWindow>
#include <QPushButton>
#include "TestController.h"

class MainWindow : public QMainWindow {
    Q_OBJECT
    QPushButton *startBtn, *stopBtn;
    TestController* controller;

public:
    MainWindow(TestController* ctrl, QWidget* parent = nullptr)
        : QMainWindow(parent), controller(ctrl)
    {
        startBtn = new QPushButton("Start", this);
        stopBtn  = new QPushButton("Stop", this);
        startBtn->move(50, 50);
        stopBtn->move(150, 50);

        connect(startBtn, &QPushButton::clicked, controller, &TestController::startTest);
        connect(stopBtn,  &QPushButton::clicked, controller, &TestController::stopTest);
    }
};

✅ UI 只负责交互,通过信号槽调用业务层接口,
无需了解通信细节或日志实现。

🧠 五、日志模块(可替换)

#pragma once
#include <QString>
#include <QDebug>

class Logger {
public:
    void log(const QString& msg) {
        qDebug() << "[LOG]" << msg;
    }
};

未来你可以轻松替换成:

  • 文件日志(写入文件)

  • 网络日志(发送到远程服务器)

  • GUI 日志面板(QTextEdit输出)
    不需要修改业务层的任何代码 → 低耦合的体现

  • 🧭 六、main.cpp(装配层,依赖注入)

  • #include <QApplication>
    #include "MainWindow.h"
    #include "SerialComm.h"
    #include "Logger.h"
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
    
        SerialComm comm;      // 可换成 PcieComm 等其他实现
        Logger logger;
        TestController controller(&comm, &logger);
        MainWindow w(&controller);
        w.show();
    
        return app.exec();
    }
    🧩 七、总结:Qt 中高内聚、低耦合的实现策略
    层级方法效果
    模块划分UI、逻辑、通信、日志独立职责单一(高内聚)
    接口抽象ICommInterface解耦依赖(低耦合)
    信号槽机制UI ↔ Controller ↔ Comm无直接依赖(低耦合)
    依赖注入main.cpp 组合对象易于扩展、可测试
    模块隔离Logger、Comm 独立可替换提高可维护性
  • 🧱 十、简短总结口诀

    高内聚:每个模块只管自己的事;
    低耦合:模块之间靠接口对话。

    在 C++ 服务系统中,这意味着:

  • 抽象接口 + 依赖注入 + 分层架构 实现松耦合;

  • 职责单一 + 内部封装 保证高内聚。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值