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 のさまざまなコレクションで見ることができます。

たとえば、ListおよびDictionaryクラスは、オブジェクトのコレクションを管理する機能を提供します。それらは継承によって共通の祖先を共有していません。これは意味がありません。ただし、それらの間の相互運用を容易にするために、同じインターフェースのいくつかを実装しています。

両方のクラスが実装してIEnumerableいます。これにより、いずれかのタイプのオブジェクトを使用するListDictionaryIEnumerable. なんと素晴らしい!

あなたのケースでは、新しいソフトウェアを設計する際に、これが問題空間にどのように適合するかを考えたいと思います。抽象クラスの継承を介してこれらのクラスに共通の祖先を与える場合、そこから継承するすべての項目が本当に基本型であることを確認する必要があります。(たとえば、AStreamWriterは です)。TextWriterクラス継承を不適切に使用すると、将来 API を構築および変更することが非常に困難になる可能性があります。

レポート用に抽象クラス を作成するとReportBaseします。すべてのレポートに必要な非常に一般的なメソッドがいくつか含まれている場合があります。おそらくそれは単にメソッドを指定するだけですRun()

次に、作成するレポートのタイプが 1 つしかないため、Reportから継承する具象クラスを定義しますReportBase。すべてが素晴らしいです。XReport次に、さらにいくつかのタイプのレポート、 、YReport、および例を追加する必要があることがわかりますZReport。それらが何であるかは実際には問題ではありませんが、動作が異なり、要件も異なります。すべてのレポートがきれいな HTML 出力を生成し、誰もが満足しています。

来週、あなたのクライアントは、PDF ドキュメントも出力したいXReportと言っています。YReportこれを解決する方法はたくさんありますがOutputPdf、抽象クラスにメソッドを追加することは明らかにお勧めできません。これらのレポートの中には、この動作をサポートすべきでない、またはサポートできないものがあるからです。

ここで、インターフェースが役立つ可能性があります。いくつかのインターフェースIHtmlReportIPdfReport. これらのさまざまな出力タイプをサポートするはずのレポート クラスが、これらのインターフェイスを実装できるようになりました。CreatePdfReports(IEnumerable<IPdfReport> reports)これにより、 IPdfReport を実装するすべてのレポートを取得し、適切な基本型が何であるかを気にせずに必要なことを実行できるような関数を作成できます。

これが役に立てば幸いです。あなたが解決しようとしている問題に慣れていないので、ここで腰から撃ちました。

于 2012-04-19T18:46:28.060 に答える
0

はい、Items を使用しないレポートの数がわからない場合は、Abastract クラスを使用できます。

別の良い考えは次のとおりです。

インターフェイスと抽象クラスの両方を作成することもできます

Interface で Sales を定義し、2 つの抽象クラスを作成します。1 つは両方を実装する Report 用で、もう 1 つは Sales を実装しない Report 用です。両方のインターフェースを実装する

最初に両方のメソッド (販売を実装する) を定義し、2 番目に販売のみを実装します。

ReportWithItemsBase または ReportWithoutItemsBase など、両方の抽象クラスに適切な名前を付けます。

このようにして、Report クラスの派生時に、自己説明型の名前付き基本クラスを実現することもできます。

于 2012-04-19T19:07:57.750 に答える