OOP和软件设计中的五大核心设计原则——SOLID原则

这些原则共同目标是让代码更灵活、可维护、可复用,是设计模式(如工厂、策略模式)的基础理论支撑。


SOLID原则解析与对应实现

1. 单一职责原则 (SRP)
  • 原则:一个类只负责一个功能。
  • 核心思想:一个类应该只有一个引起它变化的原因(即只负责一项功能)。
  • 通俗解释
    就像一个人只专注做一件事(例如厨师只管烹饪,服务员只管点餐),避免"万能类"导致代码难以维护。
  • 应用
    • QListWidget 仅负责显示列表项。
    • QScroller 仅负责处理滚动逻辑。
    • 参数配置单独封装(如setupInertialScroll函数)。
cpp 复制代码
// 职责分离:配置惯性滚动的逻辑单独封装
void setupInertialScroll(QAbstractScrollArea *scrollArea) {
    QScroller::grabGesture(scrollArea->viewport(), QScroller::TouchGesture);
    
    QScroller *scroller = QScroller::scroller(scrollArea->viewport());
    QScrollerProperties properties;
    properties.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.2);
    scroller->setScrollerProperties(properties);
}

// 主函数仅负责组装
int main() {
    QListWidget listWidget;
    setupInertialScroll(&listWidget); // 配置滚动逻辑
    // ... 添加列表项
}

2. 开闭原则 (OCP)
  • 原则:对扩展开放,对修改关闭。
  • 核心思想 :软件实体(类、模块等)应对扩展开放 ,对修改关闭
  • 通俗解释
    就像乐高积木------通过添加新积木(扩展)来构建新功能,而不是拆掉旧积木(修改原有代码)。
  • 应用
    • 通过继承或组合扩展滚动行为,而非修改现有类。
    • 示例:自定义SmoothScrollArea类,继承QScrollArea并内置惯性逻辑。
cpp 复制代码
class SmoothScrollArea : public QScrollArea {
public:
    explicit SmoothScrollArea(QWidget *parent = nullptr) : QScrollArea(parent) {
        QScroller::grabGesture(viewport(), QScroller::TouchGesture);
        QScrollerProperties properties;
        properties.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.2);
        QScroller::scroller(viewport())->setScrollerProperties(properties);
    }
};

// 使用扩展类,而非直接修改QScrollArea
SmoothScrollArea scrollArea;

3. 里氏替换原则 (LSP)
  • 原则:子类必须能替换父类且行为一致。
  • 核心思想:子类必须能够替换父类,且不破坏程序的正确性。
  • 通俗解释
    "鸭子类型"------如果它走路像鸭子、叫声像鸭子,那它就应该能当鸭子用。子类不能违背父类的行为约定。
  • 应用
    • SmoothScrollArea继承QScrollArea,确保所有父类方法仍有效。
    • 避免重写核心方法(如event()),除非明确需要修改行为。
cpp 复制代码
// 正确:子类不破坏父类行为
bool SmoothScrollArea::event(QEvent *event) {
    if (event->type() == QEvent::Scroll) {
        // 处理滚动事件,但不影响其他事件
    }
    return QScrollArea::event(event); // 确保父类逻辑仍执行
}

4. 接口隔离原则 (ISP)
  • 原则:客户端不应依赖不需要的接口。
  • 核心思想:客户端不应被迫依赖它不需要的接口。
  • 通俗解释
    就像点餐时只选自己吃的菜,而不是被迫接受一份固定套餐(包含不需要的功能)。
  • 应用
    • 若需要更灵活的滚动控制,将QScroller的配置拆分为独立接口。
    • 示例:定义IScrollBehavior接口,允许动态切换滚动策略。
cpp 复制代码
class IScrollBehavior {
public:
    virtual void applyScroll(QAbstractScrollArea *area) = 0;
};

class InertialScroll : public IScrollBehavior {
public:
    void applyScroll(QAbstractScrollArea *area) override {
        QScroller::grabGesture(area->viewport(), QScroller::TouchGesture);
        // ... 参数配置
    }
};

// 使用时注入行为
SmoothScrollArea area;
InertialScroll scrollBehavior;
scrollBehavior.applyScroll(&area);

5. 依赖倒置原则 (DIP)
  • 原则:依赖抽象而非具体实现。
  • 核心思想
    • 高层模块不应依赖低层模块,二者都应依赖抽象
    • 抽象不应依赖细节,细节应依赖抽象。
  • 通俗解释
    就像电脑的USB接口(抽象)------鼠标、键盘(细节)都依赖USB标准,而不是电脑直接依赖具体设备。
  • 应用
    • 高层模块(如主窗口)依赖IScrollBehavior接口,而非直接调用QScroller
cpp 复制代码
class MainWindow : public QMainWindow {
public:
    MainWindow(IScrollBehavior *scrollBehavior, QWidget *parent = nullptr) 
        : QMainWindow(parent), m_scrollBehavior(scrollBehavior) {
        QListWidget *list = new QListWidget(this);
        m_scrollBehavior->applyScroll(list); // 通过接口配置滚动
    }
private:
    IScrollBehavior *m_scrollBehavior;
};

// 依赖注入
InertialScroll inertialBehavior;
MainWindow window(&inertialBehavior);

最终代码结构(SOLID合规)

cpp 复制代码
// 1. 抽象接口(ISP + DIP)
class IScrollBehavior {
public:
    virtual void apply(QAbstractScrollArea *area) = 0;
};

// 2. 具体实现(SRP)
class InertialScroll : public IScrollBehavior {
public:
    void apply(QAbstractScrollArea *area) override {
        QScroller::grabGesture(area->viewport(), QScroller::TouchGesture);
        QScrollerProperties props;
        props.setScrollMetric(QScrollerProperties::DecelerationFactor, 0.2);
        QScroller::scroller(area->viewport())->setScrollerProperties(props);
    }
};

// 3. 可扩展的滚动区域(OCP + LSP)
class SmoothScrollArea : public QScrollArea {
public:
    explicit SmoothScrollArea(IScrollBehavior *behavior, QWidget *parent = nullptr) 
        : QScrollArea(parent) {
        behavior->apply(this);
    }
};

// 4. 高层模块依赖抽象(DIP)
int main() {
    InertialScroll inertialBehavior;
    SmoothScrollArea scrollArea(&inertialBehavior);
    
    QListWidget listWidget;
    SmoothScrollArea listScroll(&inertialBehavior);
    // ... 显示窗口
}

优势总结

  1. 可维护性:滚动逻辑与UI组件解耦,修改滚动行为无需改动控件代码。
  2. 可扩展性 :新增滚动策略(如弹簧效果)只需实现IScrollBehavior
  3. 可测试性:可通过Mock接口单独测试滚动行为。
  4. 灵活性:运行时动态切换滚动效果(如触屏/鼠标模式)。

通过严格遵循SOLID原则,Qt中的惯性滚动实现既满足了功能需求,又保持了代码的高内聚低耦合。

相关推荐
SelectDB15 小时前
Litefuse 开源并推出单进程轻量模式,25 秒就能跑起来的 Agent 可观测与评估平台
运维·后端·自动化运维
zzzzzz3102 天前
9K Star 炸裂开源!这个 C 语言写的代码知识图谱,把 Linux 内核索引压缩到了 3 分钟
linux·服务器·sql
XIAOHEZIcode2 天前
Linux系统鼠标偏移常见原因以及修复方案
linux·运维·游戏
用户0328472220703 天前
如何搭建本地yum源(上)
运维
大树886 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠6 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
霸道流氓气质6 天前
领域驱动设计(DDD)在 Spring Boot 微服务中的实践指南
运维·spring boot·微服务
小宇宙Zz6 天前
Maven依赖冲突
java·服务器·maven
Inhand陈工6 天前
基于台达PLC与映翰通IG502的智慧水产养殖精准投喂与远程运维解决方案
运维·人工智能·物联网·阿里云·信息与通信
酣大智6 天前
ARP代理--工作原理
运维·网络·arp·arp代理