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

我的想法是它应该是一个接口,因为其他报表可能不使用“项目”,这样我就可以实现用于给定报表类的对象。

我走远了吗?我应该还刚刚创建了一个基类吗?我不创建基类的逻辑是,并非所有报表类都可以使用“项目”,所以我不想在不使用它们的地方定义它们。

4

2 回答 2

2

为了尝试回答您的问题,抽象类用于为相关类提供共同的祖先。.Net API 中的一个示例是TextWriter. 这个类提供了一个共同的祖先,所有这些类的目的是以某种方式编写文本。

接口更适合用作不同对象的适配器,这些对象不属于同一对象“家族”但具有相似的功能。.Net API 中的各种集合就是一个很好的例子。

例如,ListDictionary类为您提供管理对象集合的能力。他们没有通过继承共享共同的祖先,这是没有意义的。但是,为了允许它们之间的轻松互操作,它们实现了一些相同的接口。

这两个类都实现了IEnumerable. 这完全允许您使用任一类型的对象ListDictionary作为任何需要IEnumerable. 多么美妙!

因此,现在在您设计新软件的情况下,您需要考虑如何将其融入您的问题空间。如果你通过继承抽象类给这些类一个共同的祖先,你必须确保从它继承的所有项目都是真正的基类型。(例如,AStreamWriter是 a TextWriter)。不恰当地使用类继承会使您的 API 在未来很难构建和修改。

假设您ReportBase为您的报告创建了一个抽象类 , 。它可能包含一些非常通用的方法,所有报告都必须具备这些方法。也许它只是指定了方法Run()

然后,您只需要生成一种类型的报告,因此您可以定义一个Report继承自ReportBase. 一切都很好。然后您发现您需要添加更多类型的报告,XReport例如,YReportZReport它们是什么并不重要,但它们的工作方式不同并且有不同的要求。所有的报告都会生成漂亮的 HTML 输出,每个人都很高兴。

下周您的客户说他们也希望XReport并且YReport能够输出 PDF 文档。现在有很多方法可以解决这个问题,但显然向OutputPdf抽象类添加方法是一个坏主意,因为其中一些报告不应该或不能支持这种行为!

现在这就是接口对您有用的地方。假设您定义了一些接口IHtmlReportIPdfReport. 现在应该支持这些不同输出类型的报表类可以实现这些接口。然后,这将允许您创建一个函数,例如,CreatePdfReports(IEnumerable<IPdfReport> reports)它可以获取所有实现 IPdfReport 的报告,并对其进行所需的任何操作,而无需关心适当的基本类型是什么。

希望这会有所帮助,因为我不熟悉您要解决的问题,所以我有点从臀部射击。

于 2012-04-19T18:46:28.060 回答
0

是的,如果您不知道有多少报表不会使用 Items ,您可以参加 Abstract 课程。

另一个好主意如下:

您还可以创建接口和抽象类

在 Interface 中定义 Sales,创建两个抽象类,一个用于实现两者的 Reports,另一个用于未实现 Sales 的 Report。实现两者的接口

首先定义这两种方法(实施销售),然后仅在第二个中实施销售。

为这两个抽象类指定适当的名称,例如 ReportWithItemsBase 或 ReportWithoutItemsBase。

这样,您还可以在派生 Report 类时实现自我解释命名基类。

于 2012-04-19T19:07:57.750 回答