2010-06-24 87 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提出它)。