SOLID——组合复用原则

组合复用原则

  • 组合复用原则
    • 主要思想
    • 代码示例分析
    • 组合复用原则体现
      • 1. 组合而非继承
      • 2. 动态功能组合
      • 3. 复用已有功能
      • 4. 接口隔离
      • 5. 单一职责
    • 优势
    • 总结

组合复用原则

组合复用原则(Composite Reuse Principle)强调在设计中优先使用对象组合而非类继承,以提高系统的灵活性和可维护性。它提倡通过组合对象来实现功能复用,避免因继承而导致的复杂类层次。

主要思想

  • 优先组合:在实现功能扩展时,应优先选择对象组合的方式,而不是通过继承创建新的子类。
  • 减少类的数量:通过组合可以减少系统中类的数量,从而降低复杂性。
  • 提高灵活性:动态组合功能使得系统能够适应变化,满足不同需求。

代码示例分析

以下是一个使用装饰模式实现的代码示例,展示了组合复用原则的应用。

#include <iostream>
using namespace std;// 抽象控件类
class Control {
public:virtual void draw() = 0; // 绘制方法virtual ~Control() {}
};// 列表控件类
class ListCtrl : public Control {
public:void draw() override {cout << "绘制普通的列表控件!" << endl;}
};// 抽象装饰器类
class Decorator : public Control {
public:Decorator(Control* tmpctrl) : m_control(tmpctrl) {}void draw() override {m_control->draw(); // 调用被装饰控件的绘制方法}
private:Control* m_control;  // 组合控件
};// 边框装饰器类
class BorderDec : public Decorator {
public:BorderDec(Control* tmpctrl) : Decorator(tmpctrl) {}void draw() override {Decorator::draw(); // 复用已有的绘制逻辑drawBorder(); // 添加边框绘制}
private:void drawBorder() {cout << "绘制边框!" << endl;}
};// 垂直滚动条装饰器类
class VerScrollBarDec : public Decorator {
public:VerScrollBarDec(Control* tmpctrl) : Decorator(tmpctrl) {}void draw() override {Decorator::draw();drawVerScrollBar();}
private:void drawVerScrollBar() {cout << "绘制垂直滚动条!" << endl;}
};// 水平滚动条装饰器类
class HorScrollBarDec : public Decorator {
public:HorScrollBarDec(Control* tmpctrl) : Decorator(tmpctrl) {}void draw() override {Decorator::draw();drawHorScrollBar();}
private:void drawHorScrollBar() {cout << "绘制水平滚动条!" << endl;}
};int main() {// 创建带边框和垂直滚动条的列表控件Control* plistctrl = new ListCtrl();Decorator* plistctrl_b = new BorderDec(plistctrl);Decorator* plistctrl_b_v = new VerScrollBarDec(plistctrl_b);plistctrl_b_v->draw(); // 绘制cout << "-------------------------------" << endl;// 创建只带水平滚动条的列表控件Control* plistctrl2 = new ListCtrl();Decorator* plistctrl2_h = new HorScrollBarDec(plistctrl2);plistctrl2_h->draw(); // 绘制// 释放资源delete plistctrl_b_v;delete plistctrl_b;delete plistctrl;delete plistctrl2_h;delete plistctrl2;return 0;
}

组合复用原则体现

1. 组合而非继承

  • 实现方式Decorator 类持有一个 Control 类型的指针 m_control,通过组合来扩展功能,而不是通过继承创建多个子类。

    class Decorator : public Control {
    public:Decorator(Control* tmpctrl) : m_control(tmpctrl) {}void draw() override {m_control->draw(); // 调用被装饰控件的绘制方法}
    private:Control* m_control;  // 组合控件
    };
    

2. 动态功能组合

  • 实现方式:在 main() 函数中,动态创建装饰器来组合不同功能。例如,创建一个带边框和垂直滚动条的列表控件。

    Control* plistctrl = new ListCtrl();
    Decorator* plistctrl_b = new BorderDec(plistctrl);
    Decorator* plistctrl_b_v = new VerScrollBarDec(plistctrl_b);
    plistctrl_b_v->draw(); // 绘制
    

3. 复用已有功能

  • 实现方式:每个装饰器通过调用 Decorator::draw() 方法复用已有的绘制逻辑。

    void draw() override {Decorator::draw(); // 复用已有的绘制逻辑drawBorder(); // 添加边框绘制
    }
    

4. 接口隔离

  • 实现方式Control 类定义了一个接口,所有控件和装饰器都实现了这个接口,降低了耦合度。

    class Control {
    public:virtual void draw() = 0; // 抽象方法virtual ~Control() {}
    };
    

5. 单一职责

  • 实现方式:每个装饰器类只负责添加特定功能,如 BorderDec 负责绘制边框。

    class BorderDec : public Decorator {
    public:void draw() override {Decorator::draw(); // 复用已有的绘制逻辑drawBorder(); // 负责绘制边框}
    private:void drawBorder() {cout << "绘制边框!" << endl;}
    };
    

优势

  • 灵活性:可以在运行时根据需要组合不同的功能,适应变化。
  • 可扩展性:通过添加新的装饰器类来扩展功能,而不需要修改已有类。
  • 降低复杂性:避免因功能组合而产生大量子类,简化类层次结构。

总结

组合复用原则通过强调对象组合而非继承,提供了一种灵活、可扩展且易于维护的设计方式。通过使用装饰模式,可以在不修改现有类的情况下,动态地扩展对象的功能,满足不断变化的需求。理解并应用这一原则,有助于提升代码的可维护性和可重用性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50918.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本匹配任务(上)

文本匹配任务 1.文本匹配介绍1.1文本匹配定义1.1.1狭义定义1.1.2广义定义 1.2文本匹配应用1.2.1问答对话1.2.1信息检索 2.文本匹配--智能问答2.1基本思路2.2技术路线分类2.2.1按基础资源划分2.2.2 答案生成方式2.2.3 NLP技术 2.3智能问答-Faq知识库问答2.3.1运行逻辑2.3.2核心关…

平衡日常工作与提升式学习话题有感

文章目录 前言1.工作是什么&#xff1f;2.怎么提升技术&#xff1f;3.工作/学习与生活的平衡总结 前言 这篇博客是针对程序员如何平衡日常编码工作与提升式学习&#xff1f;这个话题进行的个人观点阐述&#xff0c;个人所思所想罢了。 刚毕业没几年&#xff0c;水平有限&#…

QT中鼠标事件示例(包含点击,点击之后移动,释放的坐标获取)

QT中的鼠标事件 简介&#xff1a;结果展示&#xff1a;实例代码&#xff1a; 简介&#xff1a; 在Qt中&#xff0c;处理鼠标事件是图形用户界面&#xff08;GUI&#xff09;编程中的一个重要方面。Qt通过一系列的事件处理函数来支持鼠标事件的响应。这些事件包括鼠标点击&…

Python模块与包

Python的模块和包是Python编程中非常重要的概念&#xff0c;它们有助于代码的复用和组织。下面将详细介绍Python的模块和包。 文章目录 一、模块&#xff08;Module&#xff09;**定义**&#xff1a;**特点**&#xff1a;导入方式**常用模块示例**&#xff1a;自定义模块_main…

【容器安全系列Ⅲ】- 深入了解Capabilities的作用

在本系列的上一部分中&#xff0c;我们提到 Docker 容器尚未使用 time 命名空间。我们还探讨了容器在许多情况下如何以 root 用户身份运行。考虑到这两点&#xff0c;如果我们尝试更改容器内的日期和时间会发生什么&#xff1f; 为了测试这一点&#xff0c;我们先运行 docker r…

代码随想录算法训练营第三十一天| 01背包问题 二维 01背包问题 一维 416. 分割等和子集

01背包问题 二维 代码随想录 视频讲解&#xff1a;带你学透0-1背包问题&#xff01;| 关于背包问题&#xff0c;你不清楚的地方&#xff0c;这里都讲了&#xff01;| 动态规划经典问题 | 数据结构与算法_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std;…

除了vim还能怎么编辑文件

除了使用vi编辑器之外&#xff0c;还有多种方法可以在UNIX或类UNIX操作系统中修改文件。以下是一些常见的文本编辑器和命令行工具&#xff1a; nano:nano是一个简单易用的文本编辑器&#xff0c;比vi更容易上手。要使用nano编辑文件&#xff0c;输入&#xff1a; nano filename…

thinkphp8 定时任务 addArgument

在ThinkPHP8中&#xff0c;我们可以使用addArgument方法来添加命令行参数。这个方法允许我们定义命令行参数&#xff0c;并且可以指定参数的模式&#xff08;例如&#xff1a;是否必须&#xff0c;是否可选&#xff09;。 以下是一个简单的例子&#xff0c;演示如何在ThinkPHP…

Golang | Leetcode Golang题解之第338题比特位计数

题目&#xff1a; 题解&#xff1a; func countBits(n int) []int {bits : make([]int, n1)for i : 1; i < n; i {bits[i] bits[i&(i-1)] 1}return bits }

Excel数字中间指定位置插入符号——以120120加*为例

设置单元格格式——自定义 更多阅读Excel数字中间指定位置插入符号_哔哩哔哩_bilibili

【Linux】2.Linux常见指令以及权限理解(1)

文章目录 1.Xshell的一些快捷键操作2.Linux指令2.1常用指令示例2.2常用指令选项2.2.1 ls指令2.2.2 cd/pwd/shoami指令2.2.3 touch指令2.2.4 mkdir指令2.2.5 rmdir指令2.2.6 rm指令 1.Xshell的一些快捷键操作 Xshell&#xff1a; altenter&#xff1a;Xshell自动全屏&#xff0c…

计算机Java项目|基于SpringBoot的精简博客系统的设计与实现

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验&#xff0c;被多个学校常年聘为校外企业导师&#xff0c;指导学生毕业设计并参…

【目标检测】CFINet:通过由粗到精的区域提议网络和模仿学习进行小目标检测

《Small Object Detection via Coarse-to-fine Proposal Generation and Imitation Learning》 通过由粗到精的区域提议网络和模仿学习进行小目标检测 期刊&#xff1a;ICCV 2023 原文&#xff1a;https://arxiv.org/abs/2308.09534 源码&#xff1a;https://github.com/shauny…

Node.js 实现一个 HTTP/2 的例子

要在前端使用 HTTP/2&#xff0c;通常不需要在 JavaScript 代码中做特殊处理&#xff0c;因为 HTTP/2 是在网络传输层处理的&#xff0c;浏览器会自动处理请求的协议选择。然而&#xff0c;可以通过设置一个简单的项目&#xff0c;使用 HTTP/2 来加载资源&#xff0c;并通过浏览…

Linux之HTTP服务器的构建

欢迎诸位来阅读在下的博文~ 在这里&#xff0c;在下会不定期发表一些浅薄的知识和经验&#xff0c;望诸位能与在下多多交流&#xff0c;共同努力! 江山如画&#xff0c;客心如若&#xff0c;欢迎到访&#xff0c;一展风采 文章目录 参考环境参考书籍一、HTTP的工作原理1. 建立连…

Windows 11上RTX 4090深度学习与大模型微调环境安装指南

【本文原作者&#xff1a;擎创科技资深产品专家 布博士】 在安装深度学习及大模型微调环境时&#xff0c;经历了多次反复操作&#xff08;如CUDA、cuDNN、PyTorch的安装与卸载&#xff09;。为了避免走弯路&#xff0c;总结了以下步骤&#xff1a; 步骤 1&#xff1a;显卡驱动…

11-sentinel利用nacos作持久化

本文介绍sentinel配置数据的持久化方法。由于sentinel官方并没有提供持久化功能&#xff0c;大家在测试过程中也能发现sentinel服务重启后&#xff0c;原来配置的数据就丢了&#xff0c;本文就是来处理这一问题的。 做好心理准备&#xff0c;我们要修改sentinel的源代码&#…

Qt消息对话框的实现

Widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);this -> setWindowIcon(QIcon(":/picture/hp.jpg"));//设置窗口图标this -> setW…

Leetcode JAVA刷刷站(57)插入区间

一、题目概述 二、思路方向 为了解决这个问题&#xff0c;我们可以遍历给定的区间列表 intervals&#xff0c;并同时构建一个新的列表来存储最终的合并结果。遍历过程中&#xff0c;我们检查当前区间是否与 newInterval 重叠或相邻&#xff0c;并根据需要进行合并。如果不重叠…

2024新生训练营 8.20 做题活动

A 输出题罢了不讲直接看代码 #inlclude<stdio.h> int main() {printf("Eclipse First&#xff0c;the Rest Nowhere.");return 0; }B 首先要知道的是凡是大于1的整数要么是质数要么是合数&#xff0c;而1既不是质数也不是合数&#xff0c;题目问从0到n所有质数…