【发布时间】:2016-04-23 22:03:10
【问题描述】:
数据库架构如下
员工
- EmployeeID(int, pk)
- 名字(nvarchar)
- 姓(nvarchar)
- 电子邮件(nvarchar)
- EmployeeType(int)
- 工资(十进制)
- HourlyRate(十进制)
好处
- BenefitID (int, pk)
- 好处 (nvarchar)
- EmployeeID (int, fk)
Employee 表包含所有员工数据。工资字段适用于全职员工,小时费率适用于小时工。福利仅适用于全职员工。
我已经设置了一个服务类,它将返回所有员工。 我还想初始化 Salied Employee 对象的所有好处。我已经使用 switch 语句设置了对员工类型的检查,然后创建对象的实例并将其添加到集合中。
这将完美地工作。
我遇到的问题是每次添加新类型的员工时,我都必须修改 Employee 服务并添加逻辑到 switch 语句来处理新类型的员工。这打破了开闭原则。
我的问题是在这种情况下将数据从数据库加载到对象的最佳方式是什么?
public enum EmployeeType
{
FullTime =1,
PartTime =2
}
public class EmployeeBenefit
{
private string _benefit;
private Employee _employee;
public int EmployeeId { get { return Employee.Id; } }
public Employee Employee { get { return _employee; } }
public string Benefit { get { return _benefit; } }
public EmployeeBenefit(Employee emp, string benefit)
{
_benefit = benefit;
_employee = emp;
}
}
public abstract class Employee
{
public int Id { get; set; }
public abstract EmployeeType Type { get; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Email { get; set; }
}
public class SalariedEmployee: Employee
{
private ICollection<EmployeeBenefit> _benefits;
public SalariedEmployee()
{
_benefits = new List<EmployeeBenefit>();
}
public IEnumerable<EmployeeBenefit> Benefits { get {return _benefits;} }
public double Salary { get; set; }
public override EmployeeType Type
{
get { return EmployeeType.FullTime; }
}
public void AddBenefit(string benefit)
{
EmployeeBenefit ebenefit = new EmployeeBenefit(this, benefit);
if (Benefits.Contains(ebenefit))
_benefits.Add(ebenefit);
}
public void RemoveBenefit(string benefit)
{
EmployeeBenefit ebenefit = new EmployeeBenefit(this, benefit);
if(_benefits.Contains(ebenefit))
_benefits.Remove(ebenefit);
}
}
public class PartTimeEmployee : Employee
{
public override EmployeeType Type
{
get { return EmployeeType.PartTime; }
}
public double HourlyRate { get; set; }
}
public class EmployeeService
{
public IEnumerable<Employee> GetAll() {
List<Employee> _lst = new List<Employee>();
using(var db = new EmployeeContext)
{
foreach(Employee e in db.Employees)
{
switch(e.Type){
case EmployeeType.PartTime:
PartTimeEmployee pt = new PartTimeEmployee();
//initialize the values of parttime employee like hourly rate
_lst.Add(pt);
break;
case EmployeeType.FullTime:
SalariedEmployee se = new SalariedEmployee();
//initialize the value of salaried employees like benefits, salary
_lst.Add(se);
break;
}
}
}
return _lst;
}
}
【问题讨论】:
-
你可以在工厂类中移动这个逻辑......类将有工作来检查类型并创建适当类型的实例......基本上你正在移动那个类中的 switch 语句并且只需要修改那个每次上课
-
我考虑过使用工厂方法,该方法将返回一个适当的 Employee 实例,但我如何设置所有相关属性,如福利、小时费率和薪水,因为它们基于子对象。我在这里很困惑。
-
添加IPartTimeEmployee、ISalariedEmployee等接口怎么样
-
我可以将薪水和福利移动到 ISalariedEmployee 并将 HourlyRate 移动到 IPartTimeEmployee,但问题仍然是如何将数据加载到各自的属性中。我可以检查从工厂类返回的对象是否是 ISalariedEmployee 或 IPartTimeEmployee 类型并设置值,但我再次引入了检查服务类中返回的对象类型的逻辑。我的想法是对的吗?
标签: c# design-patterns