2009-11-10 52 views
4

爲什麼福勒PoEAA p。 498定義以下面的方式在空物體圖案(樣品縮短,語言是C#,但沒關係):Fowler空對象模式:爲什麼使用繼承?

public class Customer 
{ 
    public virtual string Name {get; set;} 
} 

public class NullCustomer : Customer, INull 
{ 
    public override Name 
    { 
    get { return "ImTheNull";} 
    // setter ommitted 
    } 
} 

INull被用作一個標記接口。 我真的不喜歡這種方法的原因有三:

  1. 屬性需要標記虛擬
  2. 我不能封我的實體類了
  3. 至少(N + 1)的新類型介紹(N空對象,一個標記接口)

爲什麼不是實現這樣的:

public class Customer 
{ 
    public static readonly Customer NullCustomer = new Customer(){Name = "ImtTheNullCustomer";} 

    public string Name {get; set;} 
} 

我一般都會發現所有Fowlers的例子都很好想,顯然必須有一些我在這裏錯過的東西。

+0

請勿使虛擬方法變爲虛方法,或者因爲這個原因讓類不啓動。雖然我非常尊重Martin Fowler,但他的許多涉及繼承的例子都存在明確的Java偏見。在Java方法中默認是虛擬的。在C#中,他們不是,並且設計決定是由於默認虛擬方法的問題而產生的。無論如何,如果NullCustomer將成爲有效的客戶,請使用此模式。一個很好的指標是將其與空列表進行比較。一個空的列表是一個非常好的列表,宣傳它並沒有什麼壞處。這可能不是這種情況。 – 2016-06-26 06:21:39

回答

10

繼承的原因是重寫類的行爲。你對我的想法似乎就像你要檢查你所擁有的對象是否等於NullCustomer靜態實例來做決定,然而空對象的要點是支持Liskov's substitution principle

換句話說,你使用空對象來設置引用,你不會有特殊的檢查,你只會使用它,它應該有不同的行爲(真的缺乏行爲)。

+0

您在Liskov的名字中輸入了錯字。 – 2009-11-10 19:25:51

+0

好的,所以問題是關於方法(計算等),而不是簡單的獲取設置屬性? (與Alister同樣的問題) – 2009-11-10 21:23:10

+1

是的行爲是在方法甚至屬性。注意在你的例子中,setter在空對象中缺失。這改變了基類中的行爲,其中null對象是隻讀的。 – Chap 2009-11-10 21:35:39

1

你的第二個例子有一個魔法值的問題是,如果你的類有其他項目是類的一部分,你現在必須插入檢查魔法來決定返回信息或其他適當的信息。

使用Null類,類將返回最有意義的內容,而無需進行此類檢查。

例如,在詢問數據庫後,客戶類可能會返回該用戶的總美元支出。 NullCustomer將僅能夠return 0;。有了魔法值,它會從數據庫中獲取虛擬用戶的信息,或者在做出明智的事情之前必須運行另一個特定的檢查。

+0

好吧,所以問題是關於方法(計算等),而不是簡單的獲取設置屬性。 – 2009-11-10 18:35:49

+0

0是否爲正確的默認值?這取決於你想要做什麼。您不希望將NullCustomer插入到您的數據庫中... – 2016-06-26 06:25:24

0

加入Chap所說的內容。使用Null對象模式,以便有一組默認的值是可接受的。此外,如果您嘗試在MVC中使用NullCustomer,則仍然可以訪問代表模型的對象,而不必考慮潛在的不存在的數據。 [檢查空]

0

我不是一個C#程序員,但它看起來像你的第二個例子,你可以做相當於:

Customer.NullCustomer.Name = "Not Null"; 

一般而言,對象具有的行爲,而不僅僅是數據,所以它變得更加複雜。

+0

是的,你有這個權利,其他人已經提到,但已經。無論如何感謝您的評論。 – 2009-11-10 21:22:39