web-dev-qa-db-ja.com

無料/プレミアムユーザーロールのデザインパターン

この質問は実際には複雑なJava私が大学でやっているプロジェクトについてですが、私が直面している問題に本当に似ている単純なケースを見つけることは可能です。

このシナリオでは、無料バージョンとプレミアムバージョンのアプリがあります。ユーザーはアプリを初めて登録し、デフォルトで無料版を使用します。彼がそうしたいのであれば、彼はお金を払ってプレミアムユーザーになることができます。プレミアムバージョンが「永遠に続くわけではない」という事実を強調したいので、彼はフリーユーザーステータスに戻る可能性があります。 (これは奇妙に思えるかもしれませんが、これは本当に私の研究事例ではないという事実によるものです)。

また、無料ユーザーとプレミアムユーザーの両方に共通の機能やアクションがいくつかありますが、それらは共有できないものがあることに注意することも重要です。たとえば、プレミアムユーザーは、有料ユーザー(代わりに無料ユーザーが利用できます)になるための支払い方法を持つことができません。

無料とプレミアムの両方のユーザーがユーザーだったので、最初に頭に浮かんだのは継承の使用でしたが、同じユーザーが2つの役割を切り替えることができるようにするにはどうすればよいでしょうか。

それから State Pattern を使用することを考えましたが、それでも私には正しくないと思われることがまだあります。私がそれを正しく理解している場合、すべてのメソッド(「共有のもの」だけでなく、freeUserまたはpremiumUserのみに関係するメソッドも)をインターフェイスで宣言し、不正な呼び出しが行われた場合に例外をスローする必要があります(先に述べたように、プレミアムユーザーがプレミアムバージョンの料金を支払おうとした場合)。しかし、少なくともこのソリューションでは、2つの役割を簡単に切り替えることができます。

これはごく一般的な問題のようですが、インターネット上で関連性があり、十分なものを見つけることができませんでした。

4
Giada S

要件を明確にします

次のうちどれを実装するつもりですか?

  • プレミアム/無料users(タイトルのとおり):roleベースのデザイン。アプリの1つのインスタンスに複数のユーザーが存在する可能性があります。同じアプリは、さまざまなユーザーにさまざまな動作を提供します(アクティブな役割によって異なります)。
  • プレミアム/無料app(「私たちは無料版とプレミアム版のアプリを持っています」と書きました) :アプリの1つのインスタンスが、特定の時間にすべてのユーザーに同じ動作を提供します。プレミアム動作は一時的にアクティブ化できますが、すべてのユーザーで同じです。
  • プレミアム/無料サービス(「プレミアムユーザーは、プレミアムユーザーになるための支払い方法を持つことができません "):APIを公開するか、APIへのアクセスをラップするライブラリを提供することで、内部インターフェースを本当に心配します。

実装方法

すでにわかっている状態パターンは、すべての場合に最も適切な答えのようです。要件に応じて、ユーザー状態またはアプリ状態を使用できます。

ライブラリラッパーをサービスに提供する場合、状態に関連するメソッドのみを提供することが重要な場合があります。しかし、これはあなたのライブラリにとって人生を難しくします:彼は最初に状態をクエリする必要があり、次にどの状態がどのメソッドを許可するかを知る必要があります。これはひどいことです。クライアントコードに多くの望ましくない依存関係が存在することになります。したがって、すべての状態に同じインターフェイスを提供しますが、いくつかのメソッドを追加して、メソッドを呼び出す前に呼び出すことができる機能が利用可能かどうかを確認します。

APIではなくユーザーインターフェースを提供する場合は、ユーザーリクエストに適切に対応する必要があります。そのため、機能が利用できなくなった場合は、メニューでグレー表示するか、ボタンまたはイベント処理を提供しないでください。状態依存のインターフェイスを使用すると、ユーザーインターフェイスの一貫性が難しくなります。すべての州で同じメソッドを使用することをお勧めします(最終的に「機能が利用できません。機能を購入する必要があります...」などのメッセージを生成します)。必要に応じて、hasFeatureX()などの関数を提供します。アプリが決定するのを助けます。これははるかに保守しやすくなります。新しい有料機能(別の価格で)を導入する場合、または特別な役割(たとえば、「監査人」、「管理者」など)を持っている場合は、はるかに高くなります。どの状態がどの機能へのアクセスを許可するかを簡単に定義できます。

最後に、 戦略パターン (これもユーザーまたはアプリの状態に応じて)を使用することを考えることができます。しかし、戦略は状態ではないので、適切な状態遷移を確実にするために実行する必要があることがいくつかある場合、このアプローチは機能しません。アルゴリズムが本当に交換可能な場合にのみ機能します。

1
Christophe

名前付きのパターンを少し脇に置いて、私はこのようなものから始めます。

Simple Class Structure for Users, Features and Subscriptions

ここでの一般的な考え方は、ユーザーにはサブスクリプションレベルがあり、サブスクリプションがあるということです。サブスクリプションオブジェクトには、時間範囲を含めることができます(有効期限を確認できます)。

モデルの残りの部分に基づいて、ユーザーがサブスクリプションに基づいて特定の機能にアクセスできるかどうかに関する回答を返すサービスを作成します。

4
Michael