web-dev-qa-db-ja.com

DAOはシングルトンである必要がありますか?

私はRESTful APIを開発していて、DAOをリソースに使用するのは便利だと思います。メモリを使用してそれらを格納することを計画していますが、ライブラリを使用することを決定した場合、ライブラリを使用している人にはドアを閉めたくないからです。 DAOのデータベース実装。

私の質問は、DAOをシングルトンにするかどうかです。そうでない場合、サービスにはDAOのインスタンスが含まれ、おおよそ次のようになります。

_@Path("eventscheduler")
public class EventSchedulerService {
    private IEventSchedulerDao dao = new EventSchedulerDao();

    // in case a different implementation is to be used
    public void setEventSchedulerDao(IEventSchedulerDao dao) {
        this.dao = dao;
    }

    @Path("{uniqueName}")
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament getTournament(@PathParam("name") String uniqueName) {
        return dao.get(uniqueName);
    }

    @Path("create")
    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Produces(MediaType.APPLICATION_JSON)
    public Tournament createTournament(Tournament tournament) {
        return dao.create(tournament);
    }
}
_

一方、DAOがシングルトンだったとしても、最初の行だけに大きな違いはないと思います。

_private IEventSchedulerDao dao = EventSchedulerDao.getInstance();
_

それでもIEventSchedulerDaoインスタンスを使用する必要がありますが、すべてのシングルトンはこのように機能すると思いますか?何らかの理由で、常にシングルトンを静的メソッドに関連付けているため、getInstance()を使用してユーザーにシングルトンインスタンスを表示する代わりに、これは非表示になり、ユーザーはEventSchedulerDao.get(name)を使用します。など...静的な方法で。これは何かですか、それとも私だけですか?

それで、シングルトンDAOを持っているべきですか?

余談ですが、ユーザーが独自のDAOを実装するための扉を開くことが私のアプローチで大丈夫ですか?

14
dabadaba

シングルトンは使用しません。これは認められた アンチパターン であり、テストを困難にします。私はむしろ具体的な実装では inject とし、サービスにDAOインターフェースを参照させます(さまざまな実装を挿入できるようにします)

10
Brian Agnew

A[〜#〜] d [〜#〜]ata[〜#〜] a [〜#〜 ]ccess[〜#〜] o [〜#〜]bjectは、アプリケーションに1回だけ存在する必要があります。ロジックは同じで、DAOが提供するメソッドに出入りする値が異なるだけです。

そのことを念頭に置いて、明らかに通常最初に起こることは、DAOをstrong singletonとして実装することです。つまり、ファクトリにstaticメソッドがある場合です。 getInstanceのようなクラスで、DAOのインスタンスがnullの場合は遅延ロードしてそれを返します。

構文が完全に正しくない場合、すみません、私はJavaプログラマーではありません。

class DaoSingletonFactory
{
    private static Dao dao = null;

    public static Dao getInstance()
    {
        if (DaoSingletonFactory.dao == null) {
            DaoSingletonFactory.dao = new Dao();
        }

        return DaoSingletonFactory.dao;
    }
}

class UsesDao
{
    public void someMethod()
    {
        Dao dao = DaoSingletonFactory.getInstance();
    }
}

UsesDaoクラスのコードを変更せずに実装を交換することはできないため、これはテストが非常に困難です。これは、いくつかの monkey patching を使用して実行できますが、一般的には良い方法とは見なされていません。

次に、弱いシングルトンパターンというより良い方法があります。ここでは、staticメソッドを介してインスタンスを取得せず、すべてのクラスをコンストラクターまたはセッターを介してインスタンスを作成します(EventSchedulerServiceでは、セッターインジェクションを使用しています)。

唯一の問題は、アプリケーションのライフサイクルで1回しか存在しないクラスのインスタンスに依存するすべてのクラスが、パラメーターとして同じインスタンスを取得することを確認する必要があることです。 newは、アプリケーション全体のDAOオブジェクトで1回だけ呼び出されます。

明らかに、これを追跡することは非常に困難であり、オブジェクトグラフの作成は退屈で面倒な作業です。

幸いなことに、 IoC コンテナがあり、はるかに簡単です。 Spring に加えて、Googleの Guice IoCコンテナは、Javaプログラマーの間で非常に人気があります。

IoCコンテナーを使用する場合、特定の方法で動作するように構成します。特定のクラスを構築する方法や、依存関係としていくつかのクラスが必要かどうか、依存関係がどのように見えるか(常に新しいインスタンスかシングルトンか)、コンテナがすべてを配線するかどうかを指定します。

Guiceを使用したシングルトンの例については、 このリンク を確認できます。


IoCコンテナーを使用する場合の長所と短所

長所

  • すべてのファクトリメソッドを自分で記述する必要がないため、予算を節約できます。
  • (通常)非常に単純な構成
  • 迅速な開発

短所

  • 魔法使いの魔法、クラスはどういうわけか構築され、あなたはそれがどうやって起こったのか本当に見ることができません
  • クラスのルックアップによりパフォーマンスが少し低下します(手動で記述されたファクトリーはわずかに速くなります)
4
Andy

Singleton は、概念を1つだけインスタンスとインスタンスにアクセスする方法(非常に有名な静的メソッドgetInstance()

しかし、そのすべての背後にある例がまだあります。一種の制限されたアクセス権を持つ構築オブジェクト。

あなたの場合、私はむしろDIアプローチ(依存性注入)に行きたいです。公開したコードの最初のブロックのように。ほんの少しの変化。コンストラクターを介してDAOを注入します。セッターを取り除くかどうかはあなた次第です。ランタイムの変更からコントローラーを保護する場合は、コントローラーを削除します。あなたがそのような可能性を提供したいなら、それを守ってください。

インターフェースを使用し、DAOをさらに実装するためのオープンウィンドウを提供します。必要な場合とそうでない場合があります。わずか1分で作業が完了しますが、デザインが柔軟になります。メモリ内のDAOは非常に一般的です。テスト時にmockとして非常に役立ちます。または、デフォルトのDAO実装として。

ほんのヒントです。静的リソース(オブジェクト、メソッド、定数、変数)はグローバルリソースのようなものです。グローバルが悪であるかどうかは、ニーズや好みの問題です。ただし、それらにバインドされている暗黙の欠点があります。これらはconcurrencythread-safety(Javaでは、他の言語について知らない)、シリアライズ...

だから私は注意深く静力学を使うことを勧めます

1
Laiv