《VB2008从入门到精通(PDF格式英文版)》第91章


The parameter year could be justified because most countries do have specific tax rates
and implementations that are dependent on a year。 Yet the parameter province has no justifi
cation。 Imagine trying to implement a British tax system and needing to specify a province;
when Britain does not collect ine tax at a local level。
A solution might be to redefine the interface as follows: 
Public Class Specifics
Public CanadianProvince As Province 
Public AmericanState As State 
End Class 
Public Interface ITaxAccount
Sub AddDeduction(ByVal deduction As ITaxDeduction) 
Sub AddIne(ByVal ine As ITaxIne) 
Function GetTaxRate(ByVal ine As Double; ByVal year As Integer; _ 
ByVal specifics As Specifics) As Double 
ReadOnly Property Deductions() As ITaxDeduction() 
ReadOnly Property Ine() As ITaxIne() 
End Interface 
This new implementation has a specifics parameter; which is of type Specifics。 The
purpose of Specifics is to define a class that is a hodgepodge of information that is needed to
determine the correct tax rate。 However; the Specifics approach is wrong; for the following
reasons: 
o It requires knowing the implementation; which in the case of the interface is a bad idea。
It is like going to a restaurant and saying you would like a waitress with blond hair。 
o Even if the type Specifics were acceptable; you would be adding and removing data
members depending on how many tax systems you have implemented。 That is a bad
idea and introduces maintenance issues。 
The proposed solutions are not acceptable。 Additionally; there is still the problem of
having to figure out which tax rate to use。 
Implementing Ideas with Specifics
To implement a solution; let’s first start by fixing the TaxAccount class。 The modified version
will have some type of functionality that has data members that reference the year and prov
ince。 Here is the modified and correct implementation of TaxAccount: 
…………………………………………………………Page 207……………………………………………………………
CH AP T E R 7 ■ L E AR N IN G AB O U T CO M P O N E N TS AN D C L AS S H I E R AR C HI E S 185 
Friend Class TaxAccount
Inherits BaseTaxAccount 
Private _province As Province 
Private _year As Integer 
Public Sub New (ByVal province As Province; ByVal year As Integer)
_province = province 
_year = year 
End Sub 
Public Overrides Function GetTaxRate(ByVal ine As Double) As Double 
If _year = 2008 Then 
If _province = Province。Ontario Then 
Return OntarioTax2008。TaxRate(ine) 
End If 
End If 
Throw New NotSupportedException(〃Year 〃 & _year & 〃 Province 〃 & _ 
_province & 〃 not supported〃) 
End Function 
End Class 
The fix is to add a constructor that has province and year as parameters。 This sort of fix is
quite mon; in that you don’t change the interfaces; rather you change how the implemen
tations are instantiated。 Remember that when you instantiate a specific implementation; you
know what functionality you want; and thus can give the additional parameters。 Once you are
at the interface level; you should need to use only general ideas。
Now the TaxEngine class needs to be fixed。 TaxEngine is responsible for instantiating
TaxAccount; and thus to instantiate a Canadian TaxAccount; TaxEngine needs additional
parameters; as follows: 
Friend Class TaxEngine
Inherits BaseTaxEngine 
Public Overrides Function CreateTaxAccount() As ITaxAccount
Return New TaxAccount(Province。Ontario; 2008) 
End Function 
End Class 
In the implementation of CreateTaxAccount(); the province Ontario and year 2008 are
assumed。 Thus; whenever TaxEngine is instantiated; you need to make sure that the person is
in Ontario and paying taxes for the year 2008。 The implementation solves nothing and skirts
the issue of having to figure out how to deal with someone paying their taxes in British Columbia
and the year 2009。 
If you look at the implementation of TaxEngine; you will notice it is short。 One obvious solu
tion would be to create a TaxEngine type for each province and each year。 Here are two examples: 
…………………………………………………………Page 208……………………………………………………………
186 CH AP T E R 7 ■ L E A R N IN G AB OU T CO M P O N E N TS AN D C L AS S H I E R AR C H IE S 
Friend Class Ontario2008TaxEngine
Inherits BaseTaxEngine 
Public Overrides Function CreateTaxAccount() As ITaxAccount
Return New TaxAccount(Province。Ontario; 2008) 
End Function 
End Class 
Friend Class BritishColumbia2009TaxEngine 
Inherits BaseTaxEngine 
Public Overrides Function CreateTaxAccount() As ITaxAccount
Return New TaxAccount(Province。BritishColumbia; 2009) 
End Function 
End Class 
This solution is not that bad; because to be able to instantiate the correct tax engine; you
just need to define a factory that knows which class to instantiate。 But for the problem at hand;
this solution is extremely tedious; as you could end up with hundreds; if not thousands; of
TaxEngine definitions。 You would use the specific implementation approach when you have
fewer than a dozen variations。 
The better approach is to
小说推荐
返回首页返回目录