Qt Creator 插件开发(7):Qt Creator 架构(续二)

聚合

聚合由Aggregation命名空间提供。它为我们提供一种将不同类型的QObject“粘合”在一起的能力,这样,你就可以将它们“相互转换”。使用这个命名空间中的类和函数,你就可以方便地管理相关对象。在聚合中管理的对象可以由该聚合“转换成”对象的类型。

传统实现方式

假设有一个对象实现了两个接口。那么,我们可以编写如下代码:

class Interface1
{
    ....
};
Q_DECLARE_INTERFACE("Interface1", "Interface1");

class Interface2
{
    ....
};
Q_DECLARE_INTERFACE("Interface2", "Interface2");

class Bundle : public QObject,
               public Interface1,
               public Interface2
{
    Q_OBJECT
    Q_INTERFACES(Interface1 Interface2)
    ....
};

Bundle bundle;

现在,我们有一个对象bundle,同时实现了Interface1Interface2。我们可以使用转换运算符,将bundle转换成Interface1或者Interface2

Interface1* iface1Ptr = qobject_cast<Interface1*>(&bundle);
Interface2* iface2Ptr = qobject_cast<Interface2*>(&bundle);

Qt Creator 实现方式

Qt Creator 的Aggregation库提供了一种更加简洁的方式,来定义接口,然后将其打包成一个对象。创建Aggregation::Aggregate实例,然后将对象添加进该对象。加入聚合的每一个对象都可以实现一个接口。下面的代码显示了如何创建聚合。

#include <aggregation/aggregate.h>

class Interface1 : public QObject
{
    Q_OBJECT
public:
    Interface1() { }
    ~Interface1() { }
};

class Interface2 : public QObject
{
    Q_OBJECT
public:
    Interface2() { }
    ~Interface2() { }
};

Aggregation::Aggregate bundle;
bundle.add(new Interface1);
bundle.add(new Interface2);

聚合实例 bundle 现在有两个接口的实现。如果需要转换成相应接口,可以使用如下代码:

Interface1* iface1Ptr = Aggregation::query<Interface1>(&bundle);
Interface2* iface2Ptr = Aggregation::query<Interface2>(&bundle);

利用聚合,你可以多次添加同一接口。例如:

Aggregation::Aggregate bundle;
bundle.add(new Interface1);
bundle.add(new Interface2);
bundle.add(new Interface1);
bundle.add(new Interface1);
QList<Interface1*^gt; iface1Ptrs = Aggregation::query_all<Interface1>(&bundle);

使用Aggregation的另一优点是,delete 聚合中的任一对象,都可以将整个聚合 delete 掉。例如:

Aggregation::Aggregate* bundle = new Aggregation::Aggregate;
bundle->add(new Interface1);
bundle->add(new Interface2);

Interface1* iface1Ptr = Aggregation::query(bundle);
delete iface1Ptr;
// 同时会 delete 这个 bundle 及其中所有对象
// 等价于 delete bundle

这里也许看不到使用聚合的好处,但是在后面我们涉及到真正的插件实现的时候,我们就会看到这样做的优势了。

Leave a Reply