Qt源碼中的設(shè)計模式:對象樹機制與組合模式

對象樹與組合模式的關(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)存泄漏等問題。

組合模式UML類圖

程序示例

#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類圖中說到的addremove方法,因為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)能力。退一萬步,至少能提高程序員之間的溝通效率,還是很有裨益的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容