Composite パターンの書き方をざっくり説明

Composite パターンとは

木構造を使用した再帰的なデータ構造でオブジェクトを管理するパターンです。
Composite パターン - Wikipedia

実装方法

class cNode
{
public:
    cNode(){}
    virtual ~cNode()
    {
        std::for_each(list_.begin(), list_.end(), [](cNode *node) {
            delete node;
        });
    }

    void addChild(cNode *child)
    {
        list_.push_back(child);
    }
    void update()
    {
        doUpdate();
        std::for_each(list_.begin(), list_.end(),[=](cNode *node) {
            node->update();
        });
    }
protected:
    virtual void doUpdate()
    {

    }
private:
    std::list<cNode *> list_;
};

このcNodeクラスを継承してオブジェクトを作成します。
これによりオブジェクトは自分に子ノードを設定できるようになります。

実行してみる

#define LOG(MSG) std::cout << MSG << std::endl

class cScene : public cNode
{
public:
    cScene() {}
    ~cScene() 
    {
        LOG("cScene delete");

    }
    virtual void doUpdate()override
    {
        LOG("cScene");
    }
};
class cLabel : public cNode
{
public:
    cLabel() {}
    ~cLabel() 
    {
        LOG("cLabel delete");
    }
    virtual void doUpdate()override
    {
        LOG("cLabel");
    }
};

class cGraphic : public cNode
{
public:
    cGraphic() {}
    ~cGraphic()
    {
        LOG("cGraphic delete");
    }
    virtual void doUpdate()override
    {
        LOG("cGraphic");
    }
};

class cText : public cNode
{
public:
    cText() {}
    ~cText()
    {
        LOG("cText delete");
    }
    virtual void doUpdate()override
    {
        LOG("cText");
    }
};
class cPlayer : public cNode
{
public:

    cPlayer() {}
    ~cPlayer() 
    {
        LOG("cPlayer delete");
    }
    virtual void doUpdate()override
    {
        LOG("cPlayer");
    }
};

int main()
{
    cNode *root = new cNode(); //< 全ての親
    auto scene = new cScene();
    root->addChild(scene);
    root->addChild(new cPlayer());
    scene->addChild(new cLabel());
    scene->addChild(new cGraphic());
    scene->addChild(new cText());
    root->update();
    delete root;
    return 0;
}

実行結果

f:id:haina817:20180307000245p:plain

思ったこと

cocosとか触っているとバリバリ出てくるパターンの一つですねー
すごく使い勝手は良いけど、ノードの登録をミスしてしまったら
オブジェクトの削除タイミングが意図したとおりにならずハマってしまうので注意が必要です。