7

我正在为 HR 系统开发系统。有会计员工和程序员员工。在加入公司的第一个月,员工没有被赋予任何角色。一名员工可以同时是会计师和程序员。我有以下代码所示的设计。

现在,我需要通过实现一个新功能来增强系统:

终止所有会计师。(终止意味着将员工的状态设置为 IsActive = false)。问题是我不能在不检查的情况下直接将所有会计师设置为不活动。我需要检查他是否有任何其他角色。

如何改造这些类以使终止功能更自然 OO ?

更新

我正在寻找具有 EF Database First 解决方案模型和 @AlexDev 答案的数据库架构的答案。

C# 代码

List<Accountant> allAccountants =  Get All accountants from database

public class Employee
{
    public int EmpID { get; set; }
    public DateTime JoinedDate { get; set; }
    public int Salary { get; set; }
    public bool IsActive { get; set; }
}


public class Accountant : Employee
{
    public Employee EmployeeData { get; set; }
}

public class Programmer : Employee
{
    public Employee EmployeeData { get; set; }
}

在此处输入图像描述

@AlexDev 回答

public class Employee
{
...
IList<Role> Roles;
bool isActive;

public void TerminateRole(Role role)
{
    Roles.Remove(role);
    if(Roles.Count == 0)
    {
        isActive = false;
    }
}
}

public class Role
{
 abstract string Name { get;}
}

public class ProgrammerRole : Role
{
 override string Name { get { return "Programmer"; } }
}

参考

  1. 访问外部信息的 DDD 方法
  2. 更喜欢组合而不是继承?
  3. 域模型中的继承与枚举属性
  4. 实体框架:在存储库中获取子类对象
4

4 回答 4

6

要使用您正在使用的结构,您需要会计和程序员的多重继承,此外可能会将新角色添加到系统中,而这在 C# 中不存在。您应该考虑不同的设计。一种可能:

public class Employee
{
    ...
    IList<Role> Roles;
    bool isActive;

    public void TerminateRole(Role role)
    {
        Roles.Remove(role);
        if(Roles.Count == 0)
        {
            isActive = false;
        }
    }
}

public class Role
{
    abstract string Name { get;}
}

public class ProgrammerRole : Role
{
    override string Name { get { return "Programmer"; } }
}

然后,您可以为每种类型的 Role 子类化,您可以决定只终止一个角色,或者全部终止。

于 2012-08-01T12:31:32.440 回答
1

我正在写一个新的答案,因为从你添加到我假设你不会继承角色的问题中的模式。此外,如果您使用 NHibernate,请不要忘记使用公共虚拟属性。

public class Employee
{
    ...
    public virtual IList<Role> Roles { get; set; }
    public virtual bool isActive { get; set; }

    public virtual void TerminateRole(Role role)
    {
        Roles.Remove(role);
        if(Roles.Count == 0)
        {
            isActive = false;
        }
    }
}

public class Role
{
    public virtual int RoleID { get; set; }
    public virtual string Name { get; set; } 
}

和映射:

public class EmployeeMap : ClassMap<Employee>
{
    public EmployeeMap()
    {
        Id(x => x.EmpId);
        Map(x => x.JoinedDate)
        Map(x => x.Salary);
        Map(x => x.IsActive);
        HasManyToMany(x => x.Roles).Cascade.AllDeleteOrphan().Table("EmployeeRole")
    }
}

public class RoleMap : ClassMap<Role>
{
    public RoleMap()
    {
        Id(x => x.RoleID);
        Map(x => x.RoleName);
    }
}
于 2013-06-24T12:39:21.500 回答
0
public abstract class AbstractEmployee
{
    ...
    public abstract bool IsActiveAccountant { get; set; }
    public abstract bool IsActiveProgrammer { get; set; }
    public bool IsActive() { get { return bitwise or of all roles; } }
}

public class NewEmployee : AbstractEmployee
{
    ...
    public override bool IsActiveAccountant { get; set; }
    public override bool IsActiveProgrammer { get; set; }
}

public class Programmer : AbstractEmployee
{
    ...
    public override bool IsActiveAccountant { get; set; }
    public override bool IsActiveProgrammer { get; set; }
}

缺点:

  • 添加每个新的系统范围角色后,您必须修改类

优点:

  • 你不需要找会计师
  • 程序员可以有空的 IsActiveAccountant 实现,因为无论如何这个角色对他们来说都是不活动的
  • NewEmployee 可以同时拥有多个角色

如果引入新角色的开销很大,我会坚持搜索

于 2012-08-01T12:51:35.437 回答
0

从我在更喜欢组合而不是继承中的回答?

我将首先检查 - 是否存在“is-a”关系。如果存在,我通常会检查以下内容:

基类是否可以实例化。即基类是否可以是非抽象的。如果它可以是非抽象的,我通常更喜欢构图

例如 1. 会计师是雇员。但我不会使用继承,因为可以实例化 Employee 对象。

例如 2. Book 是 SellingItem。SellingItem 无法实例化 - 它是抽象概念。因此,我将使用继承痤疮。SellingItem 是一个抽象基类(或 C# 中的接口)

于 2013-06-19T06:58:13.983 回答