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


14

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を実装するための扉を開くことは私のアプローチですか?


静的アクセサーを持つシングルトンの代わりに、IoCシングルトンを使用できます。
CodesInChaos

回答:


10

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


1
あなたの最後の文章であなたが提案することは、まさに私が正しいことをしていることですか?
ダバダバ

1
あなたは(はい)インタフェースを介して参照しているが、あなたはしていない注入(....明確にする)DAOは
ブライアンアグニュー

どういう意味ですか?セッターがありますよね?
ダバダバ

@dabadaba行private IEventSchedulerDao dao = new EventSchedulerDao();はあなたが間違っている場所です。の実装IEventSchedulerDaoはコンストラクタを介してインジェクトされ、変更されることはありません(つまり、削除されsetEventSchedulerDaoます)。
デビッドアルノ

はいわかりました。デフォルトのDAOを提供するためにそれを行っただけで、それを変更することは「オプション」になります。しかし、あなたの提案を受け入れることは、デフォルトとは異なるサービスのコンストラクタを持つことを意味し、正直に言えば、デフォルトのコンストラクタを使用するため、Jerseyでどのように機能するのか分かりません。たぶん、あなたはそれを行う方法を知っていますか?
ダバダバ

4

A D ATA A CCESS O bjectだけは本当にあなたのアプリケーションに一度存在している必要があります。ロジックは同じままで、異なるのは、DAOが提供するメソッドに出入りする値だけです。

それを念頭に置いて、通常最初に起こることは、DAOを強力なシングルトンとして実装することです。つまりstatic、ファクトリクラスにメソッドがあり、getInstancenullの場合はDAOのインスタンスを遅延ロードして返します。

構文が完全に正しくない場合、すみませんが、私は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クラスのコードを変更せずに実装を交換することはできないため、これをテストするのは非常に困難です。これは、いくつかのモンキーパッチングを介して行うことができますが、一般的に良い方法とは見なされません。

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

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

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

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

IoCコンテナーを使用する場合、特定の方法で動作するように構成します。特定のクラスを構築する方法と、依存関係として何らかのクラスが必要かどうか、依存関係がどのように見えるか(常に新しいインスタンスかシングルトンか)、およびコンテナがそれをすべて結び付けるかどうかを伝えます。

Guiceを使用したシングルトンの例については、このリンクを確認してください。


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

長所

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

短所

  • ウィザードの魔法、クラスは何らかの形で構築されており、実際にそれがどのように起こったかを見ることができない
  • クラスのルックアップによるパフォーマンスのわずかな低下(手動で記述されたファクトリーはわずかに高速になります)

1

シングルトンは、1つのインスタンスだけの概念と、インスタンスへのアクセスを取得する方法を参照しています(非常に有名な静的メソッドgetInstance()を使用

しかし、そのすべての背後にはまだインスタンスがあります。ある種の制限されたアクセスを持つビルドされたオブジェクト。

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

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

ただのヒント。静的リソース(オブジェクト、メソッド、定数、変数)はグローバルリソースのようなものです。グローバルが悪かどうかは、ニーズや好みの問題です。ただし、それらには暗黙の欠点があります。これらは、並行性スレッドセーフ(Javaでは、他の言語を知らない)、シリアル化に関連しています...

だから私は慎重に静力学を使用することをお勧めします

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.