SOLID——组合复用原则

2024-08-21 06:04
文章标签 组合 复用 原则 solid

本文主要是介绍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;}
    };
    

优势

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

总结

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

这篇关于SOLID——组合复用原则的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1092323

相关文章

hdu4869(逆元+求组合数)

//输入n,m,n表示翻牌的次数,m表示牌的数目,求经过n次操作后共有几种状态#include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdlib.h>#includ

JVM内存调优原则及几种JVM内存调优方法

JVM内存调优原则及几种JVM内存调优方法 1、堆大小设置。 2、回收器选择。   1、在对JVM内存调优的时候不能只看操作系统级别Java进程所占用的内存,这个数值不能准确的反应堆内存的真实占用情况,因为GC过后这个值是不会变化的,因此内存调优的时候要更多地使用JDK提供的内存查看工具,比如JConsole和Java VisualVM。   2、对JVM内存的系统级的调优主要的目的是减少

Go组合

摘要 golang并非完全面向对象的程序语言,为了实现面向对象的继承这一神奇的功能,golang允许struct间使用匿名引入的方式实现对象属性方法的组合 组合使用注意项 使用匿名引入的方式来组合其他struct 默认优先调用外层方法 可以指定匿名struct以调用内层方法 代码 package mainimport ("fmt")type People struct{}type Pe

组合c(m,n)的计算方法

问题:求解组合数C(n,m),即从n个相同物品中取出m个的方案数,由于结果可能非常大,对结果模10007即可。       共四种方案。ps:注意使用限制。 方案1: 暴力求解,C(n,m)=n*(n-1)*...*(n-m+1)/m!,n<=15 ; int Combination(int n, int m) { const int M = 10007; int

代码随想录训练营day37|52. 携带研究材料,518.零钱兑换II,377. 组合总和 Ⅳ,70. 爬楼梯

52. 携带研究材料 这是一个完全背包问题,就是每个物品可以无限放。 在一维滚动数组的时候规定了遍历顺序是要从后往前的,就是因为不能多次放物体。 所以这里能多次放物体只需要把遍历顺序改改就好了 # include<iostream># include<vector>using namespace std;int main(){int n,m;cin>>n>>m;std::vector<i

INDEX+SMALL+IF+ROW函数组合使用解…

很多人在Excel中用函数公式做查询的时候,都必然会遇到的一个大问题,那就是一对多的查找/查询公式应该怎么写?大多数人都是从VLOOKUP、INDEX+MATCH中入门的,纵然你把全部的多条件查找方法都学会了而且运用娴熟,如VLOOKUP和&、SUMPRODUCT、LOOKUP(1,0/....,但仍然只能对这种一对多的查询望洋兴叹。   这里讲的INDEX+SMALL+IF+ROW的函数组合,

代码随想录算法训练营Day37|完全背包问题、518.零钱兑换II、377. 组合总和 Ⅳ、70. 爬楼梯(进阶版)

完全背包问题                  和01背包最大区别就是一个物品可以重复放多次,因此遍历空间时可以从前往后。 import java.util.*;public class Main{public static void main (String[] args) {Scanner sc = new Scanner(System.in);int m = sc.nextInt

【内网】ICMP出网ew+pingtunnel组合建立socks5隧道

❤️博客主页: iknow181 🔥系列专栏: 网络安全、 Python、JavaSE、JavaWeb、CCNP 🎉欢迎大家点赞👍收藏⭐评论✍ 通过环境搭建,满足以下条件: 攻击机模拟公网vps地址,WEB边界服务器(Windows Server 2008)模拟公司对外提供Web服务的机器,该机器可以通内网,同时向公网提供服务。内网同网段存在一台Windows内网服务

PyPortfolioOpt:Python中的投资组合优化工具

PyPortfolioOpt:Python中的投资组合优化工具 在金融领域,投资组合优化是一个关键的环节,它帮助投资者在追求最大回报的同时管理风险。今天,我们将探索一个名为PyPortfolioOpt的Python库,它提供了一系列的工具和算法,用于构建和优化投资组合。 概览 PyPortfolioOpt是一个开源的Python库,专门用于金融投资组合的优化。它包括经典的有效前沿、Black

水处理过滤器运行特性及选择原则浅谈

过滤属于流体的净化过程中不可缺的处理环节,主要用于去除流体中的颗粒物或其他悬浮物。水处理过滤器的原理是利用有孔介质,从流体中去除污染物,使流体达到所需的洁净度水平。         水处理过滤器的滤壁是有一定厚度的,也就是说过滤器材具有深度,以“弯曲通 道”的形式对去除污染物起到了辅助作用。过滤器是除去液体中少量固体颗粒的设备,当流体进入置有一定规格滤网的滤筒后,其杂质被阻挡,而