2

私はこれまでにWebを読んでいましたが、すばらしい解決策が見つかりませんでした。ここで私がしたいことがあります:C++で複数のライブラリを持つシングルトンとファクトリ

私は抽象基本クラスを定義するライブラリを書いています - IFooと呼ぶことができます。

class IFoo { 
    public: 
     virtual void doSomething() = 0; 
     virtual ~IFoo() {} 
}; 

ライブラリーは、そのための実装のカップルを定義する - FooLibOneFooLibTwoそれらを呼び出すことができます。

作成プロセスをカプセル化し、具体的な実装は、いくつかのランタイムPARAMTERに応じて使用されているかを決定するために、私は私の場合ブーストでファクトリメソッド(::関数にはstdマップする工場FooFactory ::文字列を使用しますが、それはここでのポイントではないはずです)。また、新しいファクトリメソッドを登録することもできます。私が直接FooFactoryのコンストラクタで、ライブラリが提供する実装(FooLibOne、FooLibTwo)を加え、今の

class FooFactory { 
    public: 
     typedef boost::function<IFoo*()> CreatorFunction; 

     IFoo* create(std::string name); 
     void registerCreator(std::string name, CreatorFunction f); 

    private: 
     std::map<std::string, CreatorFunction> mapping_; 
}; 

- ので、彼らは常に使用できます。それは次のようになります。ライブラリコードの中にはFooFactoryを使って特定のオブジェクトなどを初期化するものもあります。私は、これまでのところ、パターンの議論が頻繁に行われているため、シングルトンパターンを使用することを控えています。おそらく複数の共有ライブラリなどと組み合わされています。

しかし、工場を回ることはやや面倒かもしれませんが、私はまだこれがシングルトンのパターンがうまくいく可能性のある機会の一つだと思います。特に私が考えるならば、図書館のユーザーは、IFooの実装を追加できなければなりません。これは(既に存在する)ライブラリコードに対してもアクセス可能でなければなりません。もちろん、Dependency Injection - 私がコンストラクタを介してファクトリのインスタンスを渡すことを意味する - このトリックを行うことができます(今のところそれを行います)。しかし、私がさらに柔軟になり、第2の動的オブジェクト作成レイヤーを導入したい場合、このアプローチは失敗します。意味:私は、動的に作成されたオブジェクト内(上記参照)dynamiclyオブジェクトを作成したい(抽象基底クラスIBARの実装を言う - BarTwoバローネをして- 再び工場BarFactory経由)。

バローネを言うことができますがIFooオブジェクトが必要ですが、BarTwoはしていません。私はまだそれを必要とするかもしれないIBAR実装の1つあるため、どのような場合にBarFactoryFooFactoryを提供する必要があります。グローバルにアクセス可能なファクトリを持つと、この問題が緩和され、特定のインターフェイスの実装によって必要とされる工場を見逃すことはありません。さらに、実装のソースファイルに直接作成メソッドを登録することもできます。

FooFactory::Instance().registerCreator("new_creator", boost::bind(...)); 

私はそれは良いアイデアだと思うので、それを実装する正しい方法は何でしょうか?私はSingletonHolderから現代C++デザインLokiライブラリも参照)のようなテンプレートアプローチを行って、工場をラップしました。しかし、私は代わりにMeyerのSingletonとして実装したいと思っています。しかし、私はまだ共有ライブラリに問題があると思います。このソリューションはGCC(およびMSVCが望ましい)で動作するはずです。私はデザインの観点からも他のアイデアを公開していますが、共通の "Singletons are evil" -rantsを避けてください。 ;-)

ありがとうございます。 (代わりにブーストもののこれらの機能のC++ 11のバージョンを使用して、彼らはとにかくほとんど同じです)

私は置く -

+7

シングルトンは悪です。 ;-)私はあなたがこれを聞きたくないことを知っていますが、少なくとも今、このコメントに投票するだけでいいと言う人がいます! –

+0

@JohnZwinck:キーストロークを保存してくれてありがとう! –

+0

"TrucBiduleFactoryFactory"を持つと、 "動的オブジェクト作成の第2層"というデザインが駄目です。 –

答えて

0

うまくいけば、コードの76行は、いくつかの単語よりも多くを話しますファクトリの定義の定義とクリエータの定義が同じ(または近くの)スコープにあるため、それぞれの作成者が依存するファクトリを「参照」できるため、ファクトリを渡す必要はありませんあまりにも多く、そしてシングルトンを避けること

車&サイレンズ:

class ISiren {}; 
class Siren : public ISiren 
{ 
public: 
    Siren() { std::cout << "Siren Created" << std::endl; } 
}; 

class ICar{}; 
class EstateCar : public ICar 
{ 
public: 
    EstateCar() { std::cout << "EstateCar created" << std::endl;} 
}; 
class PoliceCar : public ICar 
{ 
    std::shared_ptr<ISiren> siren; 
public: 
    PoliceCar(std::shared_ptr<ISiren> siren) 
     : siren(siren) 
    { 
     std::cout << "PoliceCar created" << std::endl; 
    } 
}; 

工場:

typedef std::function< std::shared_ptr<ICar>() > CreatorType; 

class CarFactory 
{ 
    std::map<std::string, CreatorType> creators; 
public: 
    void AddFactory(std::string type, CreatorType func) 
    { 
     creators.insert(std::make_pair(type, func)); 
    } 

    std::shared_ptr<ICar> CreateCar(std::string type) 
    { 
     CreatorType& create(creators[type]); 
     return create(); 
    } 
}; 

class SirenFactory 
{ 
public: // Simple factory creating 1 siren type just for brevity 
    std::shared_ptr<ISiren> CreateSiren() { return std::make_shared<Siren>(); } 
}; 

"ファクトリールート"(工場が定義されているところはどこでも主な機能):

int main() 
{ 
    CarFactory car_factory; // Car factory unaware of Siren factory 
    SirenFactory siren_factory; 

    auto EstateCarLambda = []() { 
     return std::make_shared<EstateCar>(); 
    }; // Estate car lambda knows nothing of the Siren Factory 

    auto PoliceCarLambda = [&siren_factory]() { 
     return std::make_shared<PoliceCar>(siren_factory.CreateSiren()); 
    }; // Police car creation lambda using the Siren Factory 

    car_factory.AddFactory("EstateCar", EstateCarLambda); 

    car_factory.AddFactory("PoliceCar", PoliceCarLambda); 

    std::shared_ptr<ICar> car1 = car_factory.CreateCar("EstateCar"); 
    std::shared_ptr<ICar> car2 = car_factory.CreateCar("PoliceCar"); 
} 
関連する問題