2012-04-19 4 views
0

Interfaces 및 Base 클래스에는 많은 게시물이 있지만 올바른 디자인 패턴 이해를 얻는 데 어려움을 겪고 있습니다.인터페이스 및 기본 클래스 사용 이해

보고 클래스를 작성하는 경우 모든 초기 보고서에서 구현할 핵심 속성, 메서드 등이 포함 된 인터페이스를 만드는 것이 좋습니다.

예를 들어

:

다음
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 

내 생각은 "다른 보고서는 사용할 수 없습니다 있기 때문에 인터페이스해야한다고했다 항목 ",이 방법은 주어진 보고서 클래스에 사용되는 개체를 구현할 수 있습니다.

나는 출발합니까? 내가 방금 기본 클래스를 만들었어야합니까? 기본 클래스를 작성하지 않은 나의 논리는 모든 보고서 클래스가 "항목"을 사용할 수있는 것은 아니므로 사용하지 않는 부분을 정의하고 싶지는 않았습니다.

+0

여기서 인터페이스를 구현하는 이유를 설명 할 수 있습니까? 생각하지 마라, 그것은 불필요하게 기억을주고있다. 나는 인터페이스없이 그것을 할 수있다. 권리? – Pankaj

+0

귀하의 질문에 약간 혼란 스럽습니다. 'Items'를 사용하지 않는 보고서를 더 많이 구현해야 할 필요가 있습니까? 인터페이스에 요구 사항으로 정의되어 있습니다. 현재 IReport를 구현하고자하는 클래스는'Items()'속성과'ItemTotalSales()'함수를 제공해야합니다. – Thomas

+0

Items를 포함하는 인터페이스를 구현했다고해서 반드시 사용해야하는 것은 아닙니다. – Xaisoft

답변

2

질문에 대답하려고하면 관련 클래스에 공통 조상을 제공하기 위해 추상 클래스가 사용됩니다. .Net API의 예제는 TextWriter입니다. 이 클래스는 텍스트를 어떤 방식으로 쓰는 것을 목적으로하는 모든 다양한 클래스를 공통 조상으로 제공합니다.

인터페이스는 개체의 동일한 "패밀리"에 속하지 않지만 유사한 기능을 가진 다른 개체의 어댑터 역할을하는 데 더 적절하게 사용됩니다. 이것에 대한 좋은 예가 .Net API의 다양한 콜렉션에서 볼 수 있습니다.

예를 들어 ListDictionary 클래스는 개체 컬렉션을 관리하는 기능을 제공합니다. 그들은 상속을 통해 공통 조상을 공유하지 않는다. 그러나 이들 사이의 상호 운용성을 쉽게하기 위해 동일한 인터페이스를 구현합니다.

두 클래스 모두 IEnumerable을 구현합니다. 이렇게하면 IEnumerable이 필요한 항목의 피연산자로 List 또는 Dictionary 유형의 개체를 사용할 수 있습니다. 얼마나 멋진!

이제는 새로운 소프트웨어를 설계 할 때 문제 공간에 어떻게 맞을지 생각하고 싶습니다. 이러한 클래스에 추상 클래스의 상속을 통해 공통 조상을 부여하면이 클래스에서 상속받은 모든 항목이 실제로 기본 유형인지 확인해야합니다. (예 : StreamWriterTextWriter입니다.) 클래스 상속을 부적절하게 사용하면 미래에 API를 작성하고 수정할 수 없게 될 수 있습니다.

여러분의 리포팅을 위해 추상적 클래스 인 ReportBase을 만들었다 고 가정 해 봅시다. 모든 보고서에 반드시 있어야하는 몇 가지 매우 일반적인 방법이 포함될 수 있습니다. 아마도 단순히 메서드를 지정하는 것일뿐입니다 Run()

그러면 하나의 보고서 유형 만 있으므로 에서 상속하는 구체 Report 클래스를 정의 할 수 있습니다. 모든것이 좋아. 그런 다음 예를 들어 XReport, YReportZReport 등 여러 가지 유형의 보고서를 추가해야한다는 것을 알게됩니다. 그것은 실제로 무엇인지는 중요하지 않지만, 다르게 작동하고 다른 요구 사항을 가지고 있습니다. 모든 보고서는 예쁜 HTML 출력을 생성하며 모두가 만족합니다.

다음 주에는 고객이 XReportYReport으로 PDF 문서를 출력 할 수 있다고 말합니다. 이제이 문제를 해결할 수있는 방법이 많이 있지만 분명히 추상 클래스에 OutputPdf 메서드를 추가하는 것은 좋지 않습니다. 이러한 보고서 중 일부는이 동작을 지원하거나 지원해서는 안되기 때문입니다.

이제 인터페이스가 유용 할 수 있습니다. 몇 가지 인터페이스 인 IHtmlReportIPdfReport을 정의한다고 가정 해 보겠습니다. 이제 이러한 다양한 출력 유형을 지원해야하는 보고서 클래스가 해당 인터페이스를 구현할 수 있습니다. 이렇게하면 CreatePdfReports(IEnumerable<IPdfReport> reports)과 같은 함수를 만들 수 있습니다.이 함수는 IPdfReport를 구현하는 모든 보고서를 취할 수 있으며 적절한 기본 형식을 신경 쓰지 않고도 IPdfReport와 관련하여 필요한 모든 작업을 수행 할 수 있습니다.

도움이 되었으면 좋겠어. 나는 당신이 해결하려고하는 문제에 익숙하지 않아서 여기에서 엉덩이를 쏘아보고 싶다.

+0

대단 했어, 고마워. 토마스. 이 이론을 구현하는 데 어려움을 겪고 있습니다. 시간 내 주셔서 감사합니다. – TreK

+0

문제 공간과 해결해야 할 문제에 익숙하지 않은 경우 복잡한 클래스 및 인터페이스 구조로 솔루션을 오버 엔지니어링하려고 할 때 가장 큰 제안이됩니다. 당신이 필요로하는 것을 적어두고 그것이 유익해질 것이라는 것을 깨달을 때 앞으로 나아갈 수있는 리팩터링을 기꺼이하십시오. – Thomas

+0

@TravisK는 또한 어려움을 겪는 것에 대해 나쁘지 않습니다. 좋은 디자인은 엄청나게 어렵고 처음에는 제대로 이해하기가 거의 불가능합니다. – Thomas

0

예, Items를 사용하지 않을 보고서의 수를 모르는 경우 Abastract 클래스로 이동할 수 있습니다.

또 다른 좋은 생각은 다음과 같습니다

당신은 또한

는, 인터페이스에 판매를 정의하는 두 개의 추상 클래스, 보고서가 영업을 구현하지 모두 다른 구현 보고서 하나를 만들 인터페이스와 추상 클래스를 모두 만들 수 있습니다. 둘 모두에 대한 인터페이스 구현

두 메소드 (판매 구현)를 먼저 정의하고 두 번째에만 판매를 구현하십시오.

두 추상 클래스 모두에 적절한 이름을 지정합니다. ReportWithItemsBase 또는 ReportWithoutItemsBase.

이 방법을 사용하면 Report 클래스도 파생시킬 때 명명 된 기본 클래스를 자체적으로 설명 할 수 있습니다.

+0

추가 아이디어를 제공해 주셔서 감사합니다. – TreK

관련 문제