2016-04-25 12 views
4

私はデータベースにテーブルの束を作成するInitializeメソッドを持つクラスを持っています。このクラスは、次のようになります。オブジェクトを初期化する必要があるときに使用するデザインパターン?

public class MyClass 
{ 
    private bool initialized = false; 

    public void Initialize() 
    { 
    if(!initialized) 
    { 
     //Install Database tables 
     initialized = true; 
    } 
    } 

    public void DoSomething() 
    { 
    //Some code which depends on the database tables being created 
    } 

    public void DoSomethingElse() 
    { 
    //Some other code which depends on the database tables being created 
    } 
} 

二つの方法のdoSomethingとDoSomethingElseはInitializeメソッドは、彼らがデータベース内のテーブルを持つに依存しているため先に進む前に呼び出されていることを確認する必要があります。 - コンストラクタは今非自明であり、例外を引き起こす可能性があるメソッドを呼び出す必要があるので、これは良いアイデアのように見えるしていません

  1. は、クラスのコンストラクタで初期化メソッドを呼び出します。私は2つの選択肢があります。

  2. 2つの方法のそれぞれでInitializeメソッドを呼び出します。これは、いくつかのメソッドが複数ある場合は特に優れた解決策ではありません。

これをより洗練された方法で解決できるデザインパターンがありますか?

答えて

6

私はInitializeが呼び出されたstatic factory methodを使用して、コンストラクタをプライベートに、staticファクトリメソッドの使用を強制することになります。

public class MyClass 
{ 
    private MyClass() { ... } 

    public static MyClass createInstance() { 
    MyClass instance = new MyClass(); 
    instance.Initialize(); 
    return instance; 
    } 
} 

また、私はinitialized変数を削除します - 一部ではあなたので、これ以上必要なくなりますが、スレッドの安全性のために可視性(例えば、同期、揮発性またはAtomicBoolean)を保証する手段が必要となるためです。

私はMiško Hevery'sのブログ記事はコンストラクタで仕事をしているのは面白いことだと思います。

+0

私がMyClass.createInstance()を複数回呼び出した場合、データベースは2回以上初期化されますか? – DaveH

+0

@DaveHは 'Initialize'の実装方法に完全に依存しています。 –

+0

@DaveHあなたのクラスが複数回initiliazされないようにしたい場合は、シングルトンデザインパターンを使用できます。 – Karolis

-1

シングルトンファクトリーミックスをお勧めします。クラスの1つのインスタンスだけが必要なので、クラスのメンバーとやり取りしたいと思っています。

実装例:

class MyClassSingleton 
{ 
    private MyClassSingleton() { } 

    private static object _syncRoot = new Object(); 
    private static volatile MyClassSingleton _instance; 
    public static MyClassSingleton Instance 
    { 
     get 
     { 
      if (_instance == null) 
      { 
       lock (_syncRoot) 
       { 
        if (_instance == null) 
        { 
         _instance = new MyClassSingleton(); 
         _instance.InitializeLogic(); 
        } 
       } 
      } 
      return _instance; 
     } 
    } 

    public void DoStuff() { } 

    private void InitializeLogic() 
    { 
     // DB logic. 
    } 
} 

アクセスそれ:

MyClassSingleton.Instance.DoStuff(); 

このアプローチであなただけのアプリケーションごとにクラスのインスタンスを1つ持っています。つまり、テーブルを一度だけ初期化します。

+0

@Downvoterはdownvoteの理由を提供するのに気をつけますか? – Karolis

1

私はそれに依存するタスクの定義からデータベースのインストールを分けます:アンディ・ターナー@

  • で指摘したように

    • staticファクトリは、データベースのインストールに使用することができ

      とデータベース

    上で作業を行うためのrepository pattern私が正しく理解していれば、あなたはアーカンソーので、私はこのソリューションを提案データベースに依存するタスクの数が多いことが懸念されます。

    依存性注入パターンを使用すると、リポジトリはデータベースへの参照を取得できるため、ブートストラップコードではデータベースのインストールを一度実行し、それに依存するすべてのリポジトリのデータベースへの参照を注入できます。

  • 0

    初期化を行う共同編集者の使用をお勧めします。そうすることで、MyClassは、初期化者のコラボレーターをモックに置き換えることで簡単にテストできます。たとえば:

    public class MyClass { 
    
    public MyClass(MyClassInitialiser initialiser) { 
        initialiser.initialize(); 
    } 
    
    public void DoSomething() { 
        //Some code which depends on the database tables being created 
    } 
    
    public void DoSomethingElse() { 
        //Some other code which depends on the database tables being created 
    } 
    

    }

    0

    または代替ソリューション、ここでの考え方は、あなたがMyClassの中の単一責任の原則を破っていることです。同じクラスのこれらのテーブルでは、初期化の動作(データベーステーブルのインストール)と動作が簡単です。したがって、これらの責任を2つの異なるクラスに分け、1つを共同作業者として別のクラスに渡す必要があります。

    public class MyClass { 
    
        DatabaseCollaborator collaborator; 
    
        public MyClass(DatabaseCollaborator collaborator) { 
         this.collaborator = collaborator; 
        } 
    
        public void DoSomething() { 
         //Some code which depends on the database tables being created 
         collaborator.someMethod(); 
        } 
    
        public void DoSomethingElse() { 
         //Some other code which depends on the database tables being created 
         collaborator.anotherMethod(); 
        } 
    
    } 
    
    public class DatabaseCollaborator { 
    
        DatabaseConfig config; 
    
        public DatabaseCollaborator(DatabaseConfig config) { 
         this.config = config; 
        } 
    
        public void someMethod() { 
    
        } 
    
        public void anotherMethod() { 
    
        } 
    } 
    
    public class DatabaseConfig { 
    
        public DatabaseConfig() { 
         // initialize 
        } 
    } 
    
    関連する問題