2010-06-24 88 views
4

我有3个班,二继承1:嵌套基类

public class Employee { 
    private virtual double getBonus() { ... } 
    private virtual double getSalary() { ... } 
} 

public class Nepotism : Employee { 
    private double getBonus() { ... } 
} 

public class Volunteer : Employee { 
    private double getSalary() { ... } 
} 

所以,问题是有时候会有志愿者谁得到裙带关系奖金 - 是有一些方法写的构造函数允许覆盖/嵌套基地类是这样的:

Employee Bill = new Volunteer(new Nepotism()); 

我想是这样的:

public class Volunteer : Employee { 
    private Employee _nest; 
    public Volunteer(Employee nest) 
     : base() { 
     _nest = nest; 
     // now what? 
    } 
} 

基本上我想要一些对象有两个类的覆盖。

我想避免编写重写方法来检查嵌套类。

getSalary() { 
    return (nest != null) ? nest.salary : salary; // I want to avoid this if I can 
} 

我该怎么做?我在正确的轨道上吗?我离开了吗?

+2

在您的模型中,员工确定该员工的工资。这与现实世界相匹配吗?不可以。当代码更准确地模拟业务流程时,您可能会发现您的面向对象设计更顺畅;实际决定员工工资的是组织的补偿政策*。如果薪酬政策发生变化,那么您希望仅在一个地方更新代码,而不是在六个不同的员工班级中更新代码。因此,制定一个代表公司政策的课程,并将规则放在那里。 – 2010-06-24 19:47:30

+0

同意 - 这就是为什么我与jrista的答案。这将允许将政策应用于奖金,薪水和其他未来薪酬方式。 – willoller 2010-06-24 20:29:18

+0

尽管getSalary方法可以访问规则引擎或某些其他(分离的)源工资信息。 – willoller 2010-06-24 20:36:58

回答

4

我认为你试图以不明智的方式使用继承。这种方法造成了一系列依赖性和古怪的业务规则,导致难以使用和维护的严格架构。

如果计算员工工资取决于员工以及“奖金特征”,那么这将是更好地应对所有三件事情彼此分开:

interface IBonusTrait 
{ 
    decimal ApplyBonus(Employee employee, decimal currentTotal); 
} 

class Employee 
{ 
    // ... 

    public decimal BaseSalary { get; set; } 
    public IList<IBonusTrait> BonusTraits { get; set; } 
} 

class SalaryCalculator 
{ 
    public decimal CalculateSalary(Employee employee) 
    { 
     decimal totalSalary = employee.BaseSalary; 
     foreach (IBonusTrait bonusTrait in employee.BonusTraits) 
     { 
      totalSalary = bonusTrait.ApplyBonus(employee, totalSalary); 
     } 

     return totalSalary; 
    } 
} 
+0

这很有趣,因为它可以轻松添加新的*类型*奖金以及 – willoller 2010-06-24 18:55:54

+0

正是。 :)'分离问题'和'单一责任'我的朋友......建筑师的最佳工具。 – jrista 2010-06-24 19:10:13

+0

我认为这样做很好,但是我对这种方法的担心是它违反了德米特法。 SalaryCalculator显示了令人羡慕的特征,并知道关于BonusTraits属性的私密细节。我没有试图打击你的解决方案 - 它显示了一个很好的“关注分离”和“SRP”。任何机构都有可能打破“LoD”的想法? – 2010-06-24 19:28:46

13

您可能想要考虑使用Decorator Pattern而不是子类。

它为子类提供了一种替代方法,当您可能需要将“多个”附加功能添加到类的单个实例时,这非常有用,这正是场景。

+0

真棒建议。装饰者非常适合。有一个理由,你应该赞成组成继承... – Randolpho 2010-06-24 18:47:42

+0

看起来像装饰正是我试图重塑。谢谢! – willoller 2010-06-24 18:52:28

0

如果一个对象可以同时是两个类,那么您可能需要重新考虑如何进行继承。

在我看来,如果一个志愿者有时可以得到一个裙带关系奖金,那么真的,你的志愿者类应该有一个getBonus()方法,并且这个方法真的属于基类。对于大多数志愿者来说,它会归零,但偶尔也不会 - 这没什么问题。

0

里德•科普塞已经说过,那个装饰模式是需要考虑的事情。

也有这个youtube video这是非常类似于你的情况(约翰Skeet提出它)。