建模“我是*但我也是**”

时间:2011-09-13 00:34:58

标签: c# oop entity-framework design-patterns inheritance

在[this post]中,我正在努力实现状态模式,正如@jonp建议的那样。我不太明白如何使用他发布的内容,但这导致我想到我可能正在尝试将方形钉固定在圆孔中。所以我的问题是:

如果我的网站访问者可以扮演多个角色,即User可以是VendorEmployerAdvertiser,或者所有上面,我应该使用继承吗?我已宣布:

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

等等,但当用户既是供应商又是雇主时,不同类的实例确实指向相同的底层对象......我不确定这是否可行。我该如何建模?

*更新*

感谢大家(你们都得到了一点(这是我能给予的))。过去几天,我一直在用EF,向下转换和状态模式将头发拉出来。角色方法更有意义。

4 个答案:

答案 0 :(得分:4)

这听起来像属性模式(或者我称之为)的情况非常合适。它是一种比简单继承更松散耦合的方法,可用于指定多个“行为”或在您的情况下指定User种类。它实际上并不比具有另一种物体标签的物体复杂。

实现它的最简单方法是使用具有只读属性User的具体IList<UserRole>类(在内部可能是List<T>字段)。您的UserRole课程将是抽象的,VendorRole / AdvertiserRole /等。将从中派生出来,允许您在给定用户上标记任意数量的不同角色(甚至是相同类型的角色)。这些角色还可以定义自己的自定义行为,实用程序方法等。

此外,您可以在GetRole<TRole>类上定义User方法,以便于访问特定类型的角色(假设每个User只有一个Role特定亚型)。

旁注:您也可以考虑与上述模式密切相关的decorator patern - 虽然我个人觉得这里有点矫枉过正,但在灵活性或力量方面确实没有增加任何内容。它通常只是模糊了你想要做的事情;虽然随时可以随意调查。

答案 1 :(得分:3)

如果不同的角色必须包含将使用多态和抽象方法实现的不同逻辑,那么您应该支持组合而不是继承,例如:

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()
    {
        /* ... */
    }
}

如果用户可以有多个角色,请考虑使用角色集合属性:

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;
};

这会使用户既是广告商又是供应商,而不是雇主。

答案 2 :(得分:2)

“我是*但我也是**”被称为多重继承。 C#不支持这一点,所以你不应该考虑它。

答案 3 :(得分: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; }
}

如果用户可能有多个单个角色的实例,则会弹出一个集合:

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

或者,如果可能有一堆乱七八糟的角色,如果动态添加角色,或者你有什么角色,你需要一个集合和一个基本类型。但是,如果涉及实体框架,那么动态添加的角色对我来说似乎不太可能。

class User
{
    ICollection<Role> Roles;
}