2013-01-22 56 views
3

我與目前一些老的C#代碼,基本上使用派生類型使用類型爲「財產」的唯一目的,如工作:使用Type作爲'Property'是不好的做法嗎?

public abstract class Fruit 
{ 
    public int Property { get; set; } 
} 

public class Apple : Fruit {} 

public class Pear : Fruit {} 

然後:

public void Foo(Fruit item) 
{ 
    if(item is Apple) 
    { 
     // do something 
     return; 
    } 
    if(item is Pear) 
    { 
     // do something 
     return; 
    } 

    throw new ArgumentOutOfRangeException("item"); 
} 

我會包括在BaseClass的一個枚舉屬性來指定「類型」:

public class Fruit 
{ 
    public int Property { get; set; } 

    public FruitType Type { get; set; } 
} 

public enum FruitType 
{ 
    Apple, 
    Pear 
} 

,然後用它因而:

public void Foo(Fruit item) 
{ 
    switch(item.Type) 
    { 
     case FruitType.Apple: 
      // do something 
      break; 
     case FruitType.Pear: 
      // do something 
      break; 
     default: 
      throw new ArgumentOutOfRangeException(); 
    } 
} 

我覺得前一種模式是濫用繼承,但是在重寫這段代碼之前我應該​​考慮一下嗎?

+3

這是一個非常設計的氣味 - 無論是原始版本,還是帶有枚舉的版本。改用多態性。我能想到的一個優點是,如果您無法修改需要打開的類層次結構。 – millimoose

+0

在第二個例子中,爲什麼這個類仍然是抽象的?它不應該被封住嗎? –

+0

@Eric yep不應該是抽象的,更新 – lockstock

回答

12

處理這種情況的標準「OO」方法是使DoSomething成爲水果的抽象方法。然後調用者只是調用DoSomething,知道實現將會做正確的事情。

這種方法的不足之處在於,它負責制定出用戶可能想要到抽象類作者身上所有可能的「許多事情」。

可以通過使用「訪問者模式」來減輕這種負面影響。訪問者模式是一種標準方法,可以使第三方根據值的運行時類型有效切換行爲。你可能會考慮研究它。

你的第二種方法 - 用標籤區分類型 - 是相當普遍的,可以非常有效。 Roslyn廣泛使用這種技術。 OO純粹主義者認爲它有點臭,但幸運的是我不是一個OO純粹主義者。

你的,我喜歡第二種技術的變化是:

public enum FruitKind { Apple, Orange } 
public abstract class Fruit 
{ 
    private Fruit(FruitKind kind) 
    { 
     this.Kind = kind; 
    } 
    public FruitKind Kind { get; protected set; } 
    private class Apple : Fruit 
    { 
     public Apple() : base(FruitKind.Apple) {} 
    } 
    public static Fruit MakeApple() { return new Apple(); } 
    // similarly for orange 
} 

現在唯一的方式,一個水果用戶可以決定類型是通過標籤,因爲蘋果和Orange都無法訪問。你知道沒有第三方會製作他們自己的水果,因爲唯一的Fruit構造函數是私人的。

+0

不錯,我喜歡術語'Kind'比'Type'更好。我也會研究訪問者模式。 – lockstock

+0

順便說一句你的代碼示例中有模式的名稱? – lockstock

+0

@lockstock:這是工廠方法模式的變體(http://en.wikipedia.org/wiki/Factory_method_pattern),但我不知道此模式的任何正式識別名稱。我個人認爲它是「私人子類型」。 –

相關問題