對象樹與組合模式的關(guān)系
Qt 的對象樹機制是組合模式的一種實現(xiàn),它使用了組合模式的思想來管理對象的父子關(guān)系。在 Qt 中,每個對象都可以有一個父對象,也可以有多個子對象。當(dāng)一個對象的父對象被銷毀時,它的子對象也會被銷毀。這種父子關(guān)系的管理方式就是組合模式的一種實現(xiàn)方式。
使用 Qt 的對象樹機制可以非常方便地實現(xiàn)組合模式,我們只需要在創(chuàng)建對象時,將其父對象作為構(gòu)造函數(shù)的一個參數(shù)傳遞進去,就可以自動建立父子關(guān)系。在銷毀對象時,我們只需要銷毀根對象,就可以自動銷毀其所有的子對象。這種自動管理父子關(guān)系的方式,不僅可以讓代碼更簡潔,而且可以避免出現(xiàn)內(nèi)存泄漏等問題。

程序示例
#include <QObject>
#include <QDebug>
// 抽象組件類
class Component : public QObject {
Q_OBJECT
public:
explicit Component(QObject *parent = nullptr) : QObject(parent) {}
virtual void operation() = 0;
};
// 葉子節(jié)點類
class Leaf : public Component {
public:
explicit Leaf(QObject *parent = nullptr) : Component(parent) {}
void operation() override { qDebug() << "Leaf operation."; }
};
// 容器節(jié)點類
class Composite : public Component {
public:
explicit Composite(QObject *parent = nullptr) : Component(parent) {}
void operation() override {
qDebug() << "Composite operation.";
for (QObject *child : children()) {
Component *component = qobject_cast<Component*>(child);
if (component) {
component->operation();
}
}
}
};
int main() {
Composite *root = new Composite();
Composite *composite1 = new Composite(root);
Composite *composite2 = new Composite(root);
Leaf *leaf1 = new Leaf(composite1);
Leaf *leaf2 = new Leaf(composite1);
Leaf *leaf3 = new Leaf(composite2);
/*
composite1->setParent(root);
composite2->setParent(root);
leaf1->setParent(composite1);
leaf2->setParent(composite1);
leaf3->setParent(composite2);
*/
root->operation();
delete root;
return 0;
}
不多bb,直接給出一個程序示例。可以看到,這里并沒有實現(xiàn)UML類圖中說到的add和remove方法,因為Qt已經(jīng)內(nèi)部幫你實現(xiàn)了。在構(gòu)造函數(shù)中,將父對象傳入,相當(dāng)于就是調(diào)用了add方法,將自身設(shè)置為子節(jié)點。
注釋塊中,可以看到子節(jié)點調(diào)用了setParent方法,去設(shè)置父節(jié)點。這和標(biāo)準(zhǔn)的組合模式中的父節(jié)點調(diào)用add方法,將子節(jié)點加入到子節(jié)點列表,實際上是一樣的。如果將nullptr傳入setParent方法,相當(dāng)于取消父子節(jié)點關(guān)系,其實和標(biāo)準(zhǔn)的組合模式中的remove方法是一樣的。在這里,我們不需要顯式的調(diào)用setParent方法,因為在上面的構(gòu)造函數(shù)中已經(jīng)傳入了各自的父節(jié)點,因此可以注釋掉。
QObject中的children方法,可以獲取所有的子對象(子節(jié)點)。程序示例中,operation方法獲取了所有的子對象,并調(diào)用子對象的operation方法。子對象中的operation方法一樣會進行這個過程,不斷傳遞直到最終的葉子對象(沒有子對象的節(jié)點)。當(dāng)QObject銷毀時,其實也會發(fā)生類似的過程,從而讓所有的子對象都銷毀,實現(xiàn)自動的內(nèi)存管理。
總結(jié)
其實沒什么好說的,如果熟悉Qt開發(fā),就會覺得本文講的東西太膚淺了。確實,設(shè)計模式就是在日常的開發(fā)中總結(jié)和凝練出來的套路,對于有經(jīng)驗的程序員來說,雖然不一定知道其概念,但是已經(jīng)在日常開發(fā)看到甚至已經(jīng)主動的去使用了。不過系統(tǒng)的定義好這些設(shè)計模式的具體概念,能夠讓我們從更宏觀的層面認識設(shè)計模式,提高架構(gòu)能力。退一萬步,至少能提高程序員之間的溝通效率,還是很有裨益的。