2012-11-07 15 views
5

Hey Leute, ich habe ein bisschen ein Design-Problem. Ich habe einen Tarifrechner wie folgt:Mit abstrakten generischen Klassen in Software-Design-Fabrik-Muster

Public Interface ICalculator 
Property PaymentTerm As Double 
Function Calculate() As CommissionValues 
ReadOnly Property CalculationRule As CalculationRuleEnum 
End Interface 

Public Interface IFlexibleRateCalculator 
Inherits ICalculator 
    Property TransferRate As Decimal 
End Interface 

Public Interface IFixedRateCalculator 
Inherits ICalculator 
    Property ContractRate As Decimal 
End Interface 

Public Interface IRateSettingBase 
    Property RateType As RateTypeEnum 
    ReadOnly Property Calculator As ICalculator 
End Interface 

Public MustInherit Class RateSetting 
Implements IRateSettingBase 
    Public MustOverride ReadOnly Property Calculator() As ICalculator Implements IRateSettingBase.Calculator 

ich etwas tun kann:

dim ratevalues as RateValues = RateSetting().Calculator.Calculate() 

Ziemlich einfach. Das Problem besteht darin, dass jeder Taschenrechnertyp über eigene Eigenschaften verfügt, die festgelegt werden müssen, damit die Calculate() -Methoden ordnungsgemäß funktionieren. So habe ich am Ende mit bis zu implementieren wie folgt

FlexibleRateCalculator 
Implements IFlexibleRateCalculator 
    Private mRequestedRate As Decimal 
    Public Function Calculate() As RateValues Implements ICalculator.Calculate 

FixedRateCalculator 
Implements IFixedRateCalculator 
    Private mTransferRate As Decimal 
    Public Function Calculate() As RateValues Implements ICalculator.Calculate 

Was ist der beste Weg ist, Generika und abstrakte Klassen mit einer Fabrik Muster zu erstellen, die einen Rechner eines bestimmten Typs generieren dynamisch ??

Ich brauche eine sehr generische Lösung, da viele Berechnungsraten hinzugefügt und modifiziert werden, alle mit ihren eigenen Parametern, die für die Berechnungslogik benötigt werden. Ich möchte das schnell machen und diese Ratenberechnung möglicherweise über db steuern. FYI Antworten in C# oder VB.Net sind willkommen :) Vielen Dank im Voraus!

+0

Ist das vb.net? Bitte fügen Sie ein Sprach-Tag hinzu, um mehr Aufmerksamkeit zu erhalten. –

+0

Danke. Und ja, es ist in VB.Net im Moment, aber ich kann zu C# konvertieren, so dass entweder Syntax würde helfen. Ich bin mehr mit dem Design beschäftigt. Danke noch einmal. – user1794228

Antwort

0

Behalten Sie nur die ICalculator Schnittstelle bei und konvertieren Sie die spezifischeren Schnittstellen in Klassen. Ich kann mir keinen guten Grund vorstellen, warum Sie eine Klasse erstellen würden, nur um eine Variable zu speichern, also werde ich die RateSetting vollständig loswerden.

Public Interface ICalculator 
    Property Rate As Double 
    Property PaymentTerm As Double 
    Function Calculate() As CommissionValues 
    ReadOnly Property CalculationRule As CalculationRuleEnum 
End Interface 

Public Class FlexibleRateCalculator : Implements ICalculator 

    Public Sub New(rate As Double) 
     Me.Rate = rate 
    End Sub 

    ' 
    ' ICalculator implementation goes here 
    ' 

End Class 

Public Class FixedRateCalculator : Implements ICalculator 

    Public Sub New(rate As Double) 
     Me.Rate = rate 
    End Sub 

    ' 
    ' ICalculator implementation goes here 
    ' 

End Class 

Public Enum RateType 
    Flexible = 1 
    Fixed = 2 
End Enum 

Public Class CalculatorFactory 

    Public Shared Function GetCalculator(rate As Double, type As RateType) As ICalculator 
     Select Case type 
      Case RateType.Flexible 
       Return New FlexibleRateCalculator(rate) 
      Case RateType.Fixed 
       Return New FixedRateCalculator(rate) 
      Case Else 
       Throw New ArgumentException 
     End Select 
    End Function 

End Class 

Sie erstellen Objektinstanzen durch eine Rate und eine Rate Typ der GetCalculator Methode übergeben. Ich weiß nicht, was Sie unter CalculationRule verstehen, aber wenn es für den Endbenutzer wichtig ist, sollten Sie es als zusätzlichen Parameter hinzufügen.

Sie können problemlos weitere Rechnertypen hinzufügen, die ICalculator implementieren, solange Sie nicht vergessen, die SELECT-Anweisung in der Factory-Methode zu aktualisieren.

EDIT: natürlich können Sie auch zusätzliche Eigenschaften vor dem Zurückgeben einer Objektinstanz setzen. Der Zweck dieses Musters besteht jedoch darin, sicherzustellen, dass der Endbenutzer nicht wissen muss, wie Calculate() implementiert ist. Wenn Sie für jeden Taschenrechner spezifischere Fabrikmethoden machen wollen, wird der Zweck dadurch verfehlt.

0

Kennen Sie sich mit IoC-Containern aus? Sie sollten in der Lage sein, die werkseitig bereitgestellten Dienste zu verwenden, um die entsprechenden Typen mit entsprechenden Parametern/Eigenschaften basierend auf einem bestimmten Typ (Aufzählung, Zeichenfolge usw.) zu generieren.

Wenn nicht, könnten Sie wahrscheinlich eine Factory-Klasse erstellen Das hat eine Methode, die basierend auf einem Parameter den entsprechenden Typ generiert. Diese Methode könnte ein ParamArray oder ein anderes Objekt akzeptieren, das die Eigenschaften enthält, die für die korrekte Einrichtung des Rechners erforderlich sind, und diese dann über die ICalculator-Schnittstelle zurückgeben.

Verwandte Themen