15

システムに一度だけ存在し、基本的にアプリケーションのさまざまなアクションのさまざまな権限を管理する機能を果たす PermissionManager というクラスがあるとします。現在、アプリケーションにクラスがあり、そのメソッドの 1 つで特定の権限をチェックできるようにする必要があります。このクラスのコンストラクターは現在パブリックです。つまり、API ユーザーによって使用されます。

数週間前までは、クラスに次の疑似コードをどこかで呼び出させるだけでした。

     PermissionManager.getInstance().isReadPermissionEnabled(this)

しかし、ここにいる全員がシングルトンとこの種の結合を嫌っていることに気付いたので、私が読んだシングルトンに対する議論は理にかなっているように見えるので(テストできない、結合が高いなど)、より良い解決策は何かと思っていました。

では、API ユーザーがクラスのコンストラクターで PermissionManager インスタンスを渡すことを実際に要求する必要があるのでしょうか? アプリケーションに PermissionManager インスタンスを 1 つだけ存在させたいのですが?

それとも、私はこれについてすべて間違っていて、非公開のコンストラクターと、PermissionManager のインスタンスを渡すファクトリーをどこかに持つ必要がありますか?


追加情報「依存性注入」と言うとき、DIパターンについて話していることに注意してください... Guice や Spring などの DI フレームワークは使用していません。(...まだ)

4

5 に答える 5

3

依存性注入フレームワークを使用している場合、これを処理する一般的な方法は、コンストラクターで PermissionsManager オブジェクトを渡すか、フレームワークが設定するタイプ PermissionsManager のプロパティを持つことです。

これが不可能な場合は、ファクトリを介してユーザーにこのクラスのインスタンスを取得させることをお勧めします。この場合、ファクトリは、クラスの作成時にコンストラクタに PermissionManager を渡します。アプリケーションの起動時に、最初に単一の PermissionManager を作成し、次にファクトリを作成して PermissionManager を渡します。

通常、クラスのクライアントが正しい PermissionManager インスタンスを見つけてそれを渡す場所を知ることは扱いにくいことは間違いありません (または、クラスが PermissionManager を使用するという事実を気にすることさえあります)。

私が見た妥協案の 1 つは、クラスにタイプ PermissionManager のプロパティを与えることです。プロパティが設定されている場合 (たとえば、単体テストで)、そのインスタンスを使用し、それ以外の場合はシングルトンを使用します。何かのようなもの:

PermissionManager mManager = null;
public PermissionManager Permissions
{
  if (mManager == null)
  {
    return mManager;
  }
  return PermissionManager.getInstance();
}

もちろん、厳密に言えば、PermissionManager は何らかの IPermissionManager インターフェイスを実装する必要があり、それを他のクラスが参照する必要があるため、テスト中にダミーの実装をより簡単に置き換えることができます。

于 2008-10-29T14:41:58.797 に答える
2

実際、PermissionManager を注入することから始めることができます。これにより、クラスがよりテストしやすくなります。

これがそのクラスのユーザーに問題を引き起こす場合は、ファクトリ メソッドまたは抽象ファクトリを使用させることができます。または、テストで PermissionManager をモックするために使用できる別のコンストラクターを使用している間に、PermissionManager を注入するパラメーターなしのコンストラクターを追加して呼び出すこともできます。

クラスをさらに分離すると、クラスがより柔軟になりますが、使いにくくなる可能性もあります。何が必要かは状況によって異なります。PermissionManager が 1 つしかなく、それを使用するクラスのテストに問題がない場合、DI を使用する理由はありません。人々が独自の PermissionManager 実装を追加できるようにしたい場合は、DI が最適です。

于 2008-10-29T14:44:31.147 に答える
2

依存性注入の方法にサブスクライブしている場合は、必要なクラスが何であれ、PermissionManagerそれをオブジェクト インスタンスとして注入する必要があります。そのインスタンス化を制御する (シングルトンの性質を強制する) メカニズムは、より高いレベルで機能します。Guice のような依存性注入フレームワークを使用すると、強制作業を行うことができます。オブジェクトのワイヤリングを手動で行っている場合、依存性注入は、ビジネス ロジックから離れたインスタンス化 (新しいオペレーターの作業) を行うコードのグループ化を優先します。

いずれにせよ、古典的な「capital-S」シングルトンは、依存性注入のコンテキストでは一般的にアンチパターンと見なされます。

これらの投稿は、過去に私にとって洞察力がありました。

于 2008-10-29T14:49:30.997 に答える
1

では、API ユーザーがクラスのコンストラクターで PermissionManager インスタンスを渡すことを実際に要求する必要があるのでしょうか? アプリケーションに PermissionManager インスタンスを 1 つだけ存在させたいのですが?

はい、これで完了です。依存関係がシングルトン、リクエストごと、スレッドごと、またはファクトリ メソッドのいずれであるかは、コンテナーと構成の責任です。.net の世界では、結合をさらに減らすために IPermissionsManager インターフェイスに依存することが理想的です。これは Java でもベスト プラクティスであると思います。

于 2008-10-29T15:00:56.667 に答える
0

シングルトン パターン自体は悪くありません。それを醜くしているのは、特定のクラスの単一のインスタンスのみを必要とするという要件があるため、一般的に使用される方法です。これは大きな間違いだと思います。

この場合、何らかの理由でインスタンス化可能な型にする必要がない限り、PermissionManager を静的クラスにします。

于 2008-10-29T14:22:41.783 に答える