组合复用原则
组合复用原则(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; } };
优势
- 灵活性:可以在运行时根据需要组合不同的功能,适应变化。
- 可扩展性:通过添加新的装饰器类来扩展功能,而不需要修改已有类。
- 降低复杂性:避免因功能组合而产生大量子类,简化类层次结构。
总结
组合复用原则通过强调对象组合而非继承,提供了一种灵活、可扩展且易于维护的设计方式。通过使用装饰模式,可以在不修改现有类的情况下,动态地扩展对象的功能,满足不断变化的需求。理解并应用这一原则,有助于提升代码的可维护性和可重用性。