2011-09-13 6 views
5

[this post]では、@jonpが示すように状態パターンを実装するのに苦労しています。私は彼が投稿したものをどのように使うのかは分かりませんが、丸い穴に四角いペグを合わせようとしているかもしれないとの考えにつながります。だから私の質問は:モデリング "私は*ですが、私も**です"

私は複数の役割を再生することができます自分のサイトへの訪問者を持っている場合、すなわちUserは、私は、継承を使用する必要があり、上記のAdvertiser、またはすべてをVendorEmployerだろうか?

class Vendor : User {} 
class Advertiser : User {} 

エトセトラが、ユーザーはベンダーと雇用者の両方であるときに異なるクラスのインスタンスは、本当に私はこれが働くことができるかわからない...同じ基礎となるオブジェクトを指す:私は宣言しました。どのように私はそれをモデル化するのですか?

*更新*

おかげで、誰も(あなたのすべては、(それは私が与えることができるすべてです)ポイントを得ます)。私はEF、ダウンキャスティング、そして最後の数日間の州のパターンを使って、ディープ・コピーの上に私の髪を引っ張ってきました。役割のアプローチははるかに理にかなっています。ユーザーが複数の役割を持つことができる場合を検討し、

public class User 
{ 
    public Role Role { get; set; } 
} 

public abstract class Role 
{ 
    abstract void DoRoleSpecificStuff(); 
} 

public class Vendor : Role 
{ 
    public void DoRoleSpecificStuff() 
    { 
     /* ... */ 
    } 
} 

public class Employer : Role 
{ 
    public void DoRoleSpecificStuff() 
    { 
     /* ... */ 
    } 
} 

public class Advertiser : Role 
{ 
    public void DoRoleSpecificStuff() 
    { 
     /* ... */ 
    } 
} 

:異なる役割は、例えば、多型と抽象メソッドを使用して実施される異なるロジックを含むようにしている場合

+2

多分私はC++、任意の継承を持つ言語で興味がありますか? ;-) –

+0

@Kerrek C++では、データベースから読み取った内容に基づいて動的なロールセットを継承する一意のユーザーサブタイプを動的に作成することについてはあまり役に立ちません。 –

答えて

4

(または私が呼び出す)属性パターンが非常に適切な状況のように聞こえます。単純な継承よりもはるかに緩やかに結合されたアプローチで、複数の "振る舞い"を指定したり、ケースの種類をUserに指定することができます。他の種類のオブジェクトのタグを持つオブジェクトよりも複雑なことはありません。

実装する最も簡単な方法は、具体的なUserクラスです。読み取り専用プロパティーはIList<UserRole>です(内部ではおそらくList<T>フィールドにすることができます)。 UserRoleクラスは抽象クラスで、VendorRole/AdvertiserRole/etcなどです。それから派生し、任意の数の異なるロール(同じタイプのものであっても)を特定のユーザーにタグ付けすることができます。これらのロールは、独自のカスタムビヘイビア、ユーティリティメソッドなどを定義することもできます。

また、あなたが特定のタイプのロールにアクセス容易にするために、あなたのUserクラスにGetRole<TRole>メソッドを定義することができます(各Userを仮定するだけで、特定のサブタイプの単一Roleを持っています)。

サイドノート:上記のパターンと密接に関連しているdecorator paternも考えられますが、個人的には私はそれが過度のものだと感じていますが、柔軟性やパワーに関しては何も追加していません。それはしばしばあなたがしようとしていることをあいまいにします。とにかく調査してください。

+0

これはデコレータですか?それは、私には霧のような標準的な多態的なコレクションのシナリオ、あるいは場合によっては複数の1:0-1の参照に似ています。 –

+0

@Jeffrey:まあまあですが、デコレータのパターンではありませんが、これはもっと賢明でシンプルなアプローチです。 :-) – Noldorin

+0

ちょうど私の答えを更新する...私はデコレータのパターンが明確に密接に関連しているが、少し関与していることに気づいた。 – Noldorin

3

あなたは継承上構成を好む必要がありますロールコレクションプロパティを使用して:

public IEnumerable<Role> Roles { get; set; } 

そうでない場合は、[Flags]属性を使用して列挙は、あなたが複数の役割を割り当てることができるようにする必要があるかどうかに応じて、あまりにも、細かいことができます

public class User 
{ 
    public Roles Roles { get; set; } 
} 

[Flags] 
public enum Roles 
{ 
    Advertiser = 0x0, 
    Employer = 0x1, 
    Vendor = 0x2  
} 

次のように、異なる役割の組み合わせを割り当てます:

User user = new User 
{ 
    Roles = Roles.Advertiser | Roles.Vendor; 
}; 

これにより、ユーザーは広告主とベンダーの両方になりますが、雇用者にはなりません。

+1

Um、no。 OPは、ユーザーが複数の役割を持つケースについて質問しました。 –

+2

User.Rolesがありませんでした。ロールはIEnumerable ですか? – Mathias

+0

@Jeffreyあなたのコメントを確認してください。入力時に私の答えを更新していました。 –

2

「私は*ですが、私も**です」は複数継承と呼ばれています。 C#はこれをサポートしていないので、考慮しないでください。

+4

多分、彼が求めている*コンセプト*をモデリングするのに、MIは必要ありません。 –

+0

まあ...私は知らない。 MIは上向きにモデル化するのに便利です。つまり、分類ツリーのノードが複数のルーツに属する場合(私は間違っている可能性があります)、私のケースでは継承は横向きです。言い換えれば従業員とベンダーは実際にタクソノミの兄弟です – ekkis

2

実際に継承を超えて構成されていますが、単一のユーザーが複数の役割を果たすことができる場合は、このようになります。

役割が比較的少ない場合、外部結合結果に類似した '駐車場'が機能する可能性があります。このパターンでは、Roleベースクラスは必要ありません。

class User 
{ 
    // all of these may be null if not applicable 
    VendorRole VendorRole { get; set; } 
    EmployeeRole EmployeeRole { get; set; } 
    AdvertiserRole AdvertiserRole { get; set; } 
} 

ユーザーが1つの役割の複数のインスタンスを持っている可能性がある場合は、コレクションがポップアップ表示さ:また

class User 
{ 
    // all of these may be null if not applicable 
    VendorRole VendorRole { get; set; } 
    EmployeeRole EmployeeRole { get; set; } 
    ICollection<AdvertiserRole> AdvertiserRoles { get; } 
} 

、役割が動的に追加されます場合は、役割の厄介な山が存在する可能性がある場合、またはあなたは何を持っていますか?コレクションとベースタイプが必要です。しかし、Entity Frameworkが関与している場合、動的に追加されたロールは私にはあり得ないようです。

class User 
{ 
    ICollection<Role> Roles; 
} 
関連する問題