たぶん究極のC++ライブラリ、Lokiを使う - AbstractFactory

since: 2002-06-27 update: 2002-06-27 count: 32965

いよいよデザインパターンのジェネリックな実装です。 テンプレートメタプログラミングによって再利用可能な設計を実装する、 とかいうジャンルですね。 設計を実装するなんて、なんとも矛盾した響きなのですが。

内部実装は結構いっちゃってますが、 外身を見るだけならGoFを読んでればまあ、余裕です。

私は残念ながら AbstractFactory パターンを使うのが適する 複数の継承ツリーを差しかえる場面に出逢ったことが無いのですが、 まあ、AbstractFactory パターンを使うべき場面なのであれば これが凄く役に立つことが容易に想像できます。

では、使用例。本の利用法のそのまんまですが…

class Soldier {
public:
    virtual void what() const =0;
};

class EasySoldier : public Soldier {
public:
    virtual void what() const {
        std::cout << "EasySoldier" << std::endl;
    }
};

class NormalSoldier : public Soldier {
public:
    virtual void what() const {
        std::cout << "NormalSoldier" << std::endl;
    }
};

class Monster {
public:
    virtual void what() const =0;
};

class EasyMonster : public Monster {
public:
    virtual void what() const {
        std::cout << "EasyMonster" << std::endl;
    }
};

class NormalMonster : public Monster {
public:
    virtual void what() const {
        std::cout << "NormalMonster" << std::endl;
    }
};

GoFを知っていればすぐに AbstractFactory が欲しくなる局面です。 JavaプログラマならGoFを片手に設計の再利用にかかるところですが、 我等が c++ & Loki では…

typedef Loki::AbstractFactory<
    TYPELIST_2(Soldier, Monster)> AbstractEnemyFactory;

typedef Loki::ConcreteFactory<
    AbstractEnemyFactory, Loki::OpNewFactoryUnit,
    TYPELIST_2(EasySoldier, EasyMonster)
    > EasyFactory;
typedef Loki::ConcreteFactory<
    AbstractEnemyFactory, Loki::OpNewFactoryUnit,
    TYPELIST_2(NormalSoldier, NormalMonster)
    > NormalFactory;

実装も再利用できます。これでおしまい。とても簡単。

それで、使いかたは…

{
    std::auto_ptr<AbstractEnemyFactory> factory(new EasyFactory);

    // ここから下は同じコード
    std::auto_ptr<Soldier> soldier(factory->Create<Soldier>());
    std::auto_ptr<Monster> monster(factory->Create<Monster>());
    soldier->what();
    monster->what();
}
{
    std::auto_ptr<AbstractEnemyFactory> factory(new NormalFactory);

    // ここから下は同じコード
    std::auto_ptr<Soldier> soldier(factory->Create<Soldier>());
    std::auto_ptr<Monster> monster(factory->Create<Monster>());
    soldier->what();
    monster->what();
}

こんな感じです。最初に Easy なり Normal なりを決定してしまえば、 後は何も考えずに factory->Create しとけば良いのです。

サンプルコード


home / index

全てリンクフリーです。 コード片は自由に使用していただいて構いません。 その他のものはGPL扱いであればあらゆる使用に関して文句は言いません。 なにかあれば下記メールアドレスへ。

shinichiro.hamaji _at_ gmail.com / shinichiro.h