2012-04-19 144 views
0

我知道在接口和基類中有很多貼子,但我很難得到正確的設計模式理解。瞭解接口和基類的使用

如果我要編寫一個報告類,我的初始階段應該是創建一個包含所有報告將實現的核心屬性,方法等的接口。

例如:

Public Interface IReportSales 

Property Sales() As List(Of Sales) 
Property ItemTotalSales() As Decimal 

End Interface 

Public Interface IReportProducts 

Property Productss() As List(Of Inventory) 
Property ProductsTotal() As Decimal 

End Interface 

那麼,我想我會一個類來實現的接口:

Public Class MyReport 
Implements IReportSales 


Public Property Sales() As System.Collections.Generic.List(Of Decimal) Implements IReportItem.Sales 
    Get 
     Return Sales 
    End Get 
    Set(ByVal value As System.Collections.Generic.List(Of Decimal)) 
     Items = value 
    End Set 
End Property 

Public Function ItemTotalSales() As Decimal Implements IReport.ItemTotalSales 
    Dim total As Decimal = 0.0 
    For Each item In Me.Sales 
     total = total + item 
    Next 
End Function 

End Class 

我的想法是,它應該是一個接口,因爲其他報告不得使用「項目「,這樣我可以實現用於給定報表類的對象。

我會離開嗎?我還應該創建一個基類嗎?我沒有創建基類的邏輯是,並非所有的報告類都可以使用「Items」,所以我不想將它們定義在不被使用的地方。

+0

你能解釋在這裏實現接口的原因嗎?你不覺得,這是給內存不必要的。我可以做到沒有界面。對? – Pankaj 2012-04-19 18:17:36

+0

你的問題對我有點困惑。你擔心實施更多不使用「項目」的報告?儘管如此,你已經在界面中定義了它。就目前而言,任何想要實現'IReport'的類都必須提供'Items()'屬性和'ItemTotalSales()'函數。 – Thomas 2012-04-19 18:17:37

+0

僅僅因爲你實現了一個包含Items的接口並不意味着你需要使用它。 – Xaisoft 2012-04-19 18:24:39

回答

2

爲了試圖回答你的問題,抽象類被用來爲相關類提供一個共同的祖先。 .Net API中的一個示例是TextWriter。這個類提供了一個共同的祖先所有各種類,其目的是以某種方式寫文本。

接口更適合用作適用於不屬於同一對象「家族」但具有類似功能的不同對象的適配器。在.Net API中的各種集合中可以看到一個很好的例子。

例如,ListDictionary類提供了管理對象集合的功能。他們不通過繼承分享共同的祖先,這是沒有道理的。爲了讓它們之間容易互操作,它們實現了一些相同的接口。

這兩個類實現IEnumerable。這乾淨地允許您使用ListDictionary任一類型的對象作爲任何需要IEnumerable的操作數。多麼美妙!

因此,現在在您設計新軟件的情況下,您想要考慮如何將它融入您的問題空間。如果您通過繼承抽象類來爲這些類提供一個共同的祖先,那麼您必須確保從它繼承的所有項都是真正的基本類型。 (例如,A StreamWriterTextWriter)。不恰當地使用類繼承可能會使您的API在將來非常難以構建和修改。

假設您爲您的報表製作抽象類ReportBase。它可能包含一些非常通用的方法,所有報告都必須具備。也許它只是指定了方法Run()

然後您只有一種類型的報告,因此您需要定義一個從ReportBase繼承的具體Report類。一切都很好。然後,您發現需要添加更多類型的報告,例如XReportYReportZReport。它們並不重要,但它們的工作方式不同,並有不同的要求。所有的報告生成漂亮的HTML輸出,每個人都很開心。

下週您的客戶說他們想要XReportYReport也能夠輸出PDF文檔。現在有很多方法可以解決這個問題,但顯然在抽象類中添加OutputPdf方法是一個糟糕的主意,因爲其中一些報告不應支持或不支持此行爲!

現在,這是接口可能對您有用的地方。假設您定義了幾個接口IHtmlReportIPdfReport。現在,應該支持這些不同輸出類型的報表類可以實現這些接口。然後,您可以創建一個函數,如CreatePdfReports(IEnumerable<IPdfReport> reports),它可以接受所有實現IPdfReport的報告,並執行它們需要的任何操作,而不必關心適當的基本類型。

希望這會有所幫助,因爲我不熟悉你正在嘗試解決的問題,所以我在這裏從臀部開槍。

+0

這很棒,謝謝@Thomas。這是完全意義上的,我只是很難實施這個理論。我很欣賞你的時間。 – TreK 2012-04-19 18:54:07

+0

如果您不熟悉問題空間以及您將要解決的問題,那麼對於您來說,我最大的建議就是不要陷入過度設計具有複雜類和界面結構的解決方案。寫下你需要的東西,隨着你意識到它會變得有益,願意重構未來。 – Thomas 2012-04-19 18:57:09

+0

@TravisK也不會因爲遇到困難而感到不快。好的設計難以置信,幾乎(或可能從字面上)不可能第一次正確地獲得。 – Thomas 2012-04-19 19:00:06

0

是的,如果你不知道有多少報告不打算使用物品,你可以去Abastract類。

另一個不錯的想法如下:

您還可以創建接口和抽象類

定義銷售在接口方面,創建兩個抽象類,一個用於實現兩個,另一個用於報告未實現銷售報告。執行界面爲

在第一個定義方法(實現銷售),並且只實現第二個銷售。

爲這兩個抽象類給出合適的名稱,例如ReportWithItemsBase或ReportWithoutItemsBase。

通過這種方式,您還可以在派生Report類時自行解釋指定的基類。

+0

感謝您的額外想法。 – TreK 2012-04-19 19:17:40