在[this post]中,我正在努力实现状态模式,正如@jonp建议的那样。我不太明白如何使用他发布的内容,但这导致我想到我可能正在尝试将方形钉固定在圆孔中。所以我的问题是:
如果我的网站访问者可以扮演多个角色,即User
可以是Vendor
,Employer
,Advertiser
,或者所有上面,我应该使用继承吗?我已宣布:
class Vendor : User {}
class Advertiser : User {}
等等,但当用户既是供应商又是雇主时,不同类的实例确实指向相同的底层对象......我不确定这是否可行。我该如何建模?
*更新*
感谢大家(你们都得到了一点(这是我能给予的))。过去几天,我一直在用EF,向下转换和状态模式将头发拉出来。角色方法更有意义。
答案 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;
}