2016-11-18 8 views
1

私にはクラスFooがあります。クラスは複数のコンストラクタを持っています。コンストラクタを選択するためのより良いパターン

class Foo 
{ 
public: 
Foo(Param1, Param2); 
Foo(Param1, Param3, Param4); 
Foo(Param1, Param4); 
Foo(Param1, Param2, Param4); 
} 

コンストラクタへのparamsの実際のリストは大きく、私は他のプロジェクト(そうでない場合、私はこれらの4つのコンストラクタをエクスポートする必要があります)から直接これらのコンストラクタへのアクセスを提供する必要はありません。私はそのような複数のコンストラクタが避けるために最良のパターンを知っているビルダパターンです。しかし、これは、このクラスのクライアントにとって、paramはオプションであり、paramはオプションではないという混乱を招きます。さらに、各コンストラクターは、パラメーターに基づいて特定の検証を行います。したがって、実際にこのオブジェクトのメソッドを使用する前に、このような検証を行うために共通の場所が必要です。

  1. 変更なしFooクラス:

    ので、現在私たちが計画しているものは、以下のようなものです。

  2. FooParam構造体

    struct FooParam 
    { 
        Param1 p1; 
        Param2 p2; 
        Param3 p3; 
        Param4 p4; 
    } 
    
  3. ファクトリーを定義します。どのようにしてください

    Foo* CreateFoo(FooParams& foo) 
    { 
        if(foo.Param2) 
        { 
         if(foo.Param4) 
         { 
          return new Foo(foo.param1, foo.param2, foo.param4); 
         } 
         else 
          return new Foo(foo.param1, foo.param2); 
        } 
        else if(foo.param4) 
        { 
         if(foo.param3) 
          return new Foo(foo.param1, foo.param3, foo.param4); 
         else 
          return new Foo(foo.param1, foo.param4); 
        } 
    
        throw new Exception("Invalid Parameter"); 
    } 
    
私たちは、ステップ3で、より良い行うことができると思い

しかし、今の?ユーザーとして

+1

param1のデータ型は何ですか? –

+2

デフォルト値のオプションもあります –

+0

複数のコンストラクタの利点は、どのパラメータが一緒になっているかが非常に明確であることです。 'struct FooParam'はすべてが複雑になっているようです。なぜコンストラクタをエクスポートできないのですか? – Gene

答えて

-1

私はいくつかの(多分NULL)パラメータを渡すstructをconstrucなければならないのはなぜ、私が

Foo* CreateFoo(Param1* P1, Param2* P2, Param3* P3, Param4* P4); 

を好みますか?

1

あなたには、いくつかの理由から、あなたのコンストラクタを公開したくない場合は、簡単にテンプレートや完璧な転送に基づいてファクトリメソッドの後ろにそれらを隠すことができます。実行時に何かを投げる

class Foo { 
    // defined somewhere 
    Foo(Param1, Param2); 
    Foo(Param1, Param3, Param4); 
    Foo(Param1, Param4); 
    Foo(Param1, Param2, Param4); 

private: 
    template<typename... Args> 
    static auto factory(Args&&... args) { 
     Foo foo{std::forward<Args>(args)...}; 
     // do whatever you want here 
     return foo; 
    } 
} 

必要はありません。
これらのパラメータを受け入れるコンストラクタが存在しない場合は、コンパイル時エラーが発生します。


そうでない場合は、それを行うの他の慣用的な方法は、named constructorsを使用することです。
私はコピー&ペースト上記のリンクから直接の例を:

class Game { 
public: 
    static Game createSinglePlayerGame() { return Game(0); } 
    static Game createMultiPlayerGame() { return Game(1); } 

protected: 
    Game (int game_type); 
}; 

がわからない、これはとにかくあなたの要件に適合します。このことの利点何を考え、言っ


CreateFoo({ Param1V, Param3V }); 

またはさらに悪いことに、この:この代わりの

FooParams params{ Param1V, Param3V }; 
CreateFoo(params); 

new Foo{Param1V, Param3V}; 

中級クラスを導入することであなたのクラスのユーザーを実際に助けているわけではありません。
彼らは、特定の場合に必要なパラメータが何であるかを覚えておく必要があります。

関連する問題