梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈��梓囚徒貧議 Enter 囚辛指欺云慕朕村匈��梓囚徒貧圭�鮗� ● 辛指欺云匈競何��
!!!!隆堋響頼��紗秘慕禰厮宴和肝写偬堋響��
existed�察�TaxEngine。CalculateTaxToPay�┌� would have needed to call the base class functionality
to get the basic tax rate�察�and then recalculate the taxable monies to figure out if the surtax applied。
*Note When you use Overrides with methods�察�you are saying that you need something special。 This does
not imply that the base class functionality will be called。 It implies that you might call the base class functionality
and perform some additional operations。 Thus�察�when designing base class functionality�察�it is important to
track calculations or operations using protected data members。 The data members avoid having derived classes
perform the same operations multiple times�察�slowing down the application and avoiding potential errors。
USING NAMESPACES
Namespaces are used to define classes�察�interfaces�察�and structures that belong together。 In this chapter¨s
example�察�there is an American tax engine�察�a Swiss tax engine�察�and so on。 For organizational purposes�察�each
should have its own namespace。 Sometimes you might even create a custom assembly for each set of inter
face implementations�察�but you would still need to create a namespace。 Creating a namespace is independent
of the fact of whether or not you create a separate assembly。
In the examples�察�I use namespaces like Surtax and Canada。 Whenever you create a class or a module�察 �
or some other type�察�you can embed the type within the namespace。 Then to use the newly defined
namespaces in code pieces that are not part of the namespace�察�use the Imports keyword。
Abstracting Instantiations with Factories
Take a good look at the scope declaration of the tax engine shown earlier and pare it with
the scope declaration for the ITaxEngine interface。 What you will notice is that ITaxEngine is
declared as Public scope�察�as is BaseTaxEngine�察�and TaxEngine is declared as Friend。 Going back
to our project structure�察�this scope declaration implies that any reference to LibTax will see the
interface ITaxEngine and BaseTaxEngine�察�but not TaxEngine。 For example�察�the following test
code will not work。
Dim taxengine As ITaxEngine = New Surtax。TaxEngine�┌�
The reason the test code will not work is that any type that is not declared with Public scope
is private to the solution containing the declaration。 You may be thinking�察 �That¨s great!you
declare a type that you cannot instantiate。 So�察�how can I use that type�拭院�
The scope declarations are not a mistake and illustrate a design pattern called a factory 。 A
factory is a way of abstracting the instantiation away from the caller so that the interface can
vary from its implementation。 In our restaurant analogy�察�it means when you want a waiter�察�you
´´´´´´´´´´´´´´´´´´´´´´Page 200´´´´´´´´´´´´´´´´´´´´´´´
178 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
don¨t want to need to know his name。 You would rather have a generic mechanism where the
restaurant presents to you the waiter。 Otherwise�察�to eat at a restaurant�察�you would need to
know the name of your waiter before being able to order something。 That would be inefficient。
The correct way of defining a factory is as follows�此�
Public Module EngineCreator
Public Function CreateSurtaxTaxEngine�┌� As ITaxEngine
Return New Surtax。TaxEngine�┌�
End Function
' Required for country´specific tax calculations
Public Function CreateCanadianTaxEngine�┌� As ITaxEngine
Return New Canada。TaxEngine�┌�
End Function
End Module
The factory is typically declared in a module because a module is not instantiated。 Generally
speaking�察�you don¨t want to add a factory to an object that can be instantiated because it could
result in context´specific instantiation。 In other words�察�you usually want a fresh object created
from scratch each time�察�so it¨s not affected by the current state of the application。 In the imple
mentation of CreateSurtaxTaxEngine�┌��察�the type Surtax。TaxEngine is instantiated�察�and the
instance is cast to the interface type ITaxEngine。
The EngineCreator module is declared with public scope�察�implying any code that references
the assembly can see the module。 Thus�察�the test code can be rewritten as follows ��we need to
import the LibTax project�察�of course���此�
Dim taxengine As ITaxEngine = EngineCreator。CreateSurtaxTaxEngine�┌�
After calling EngineCreator。CreateSurtaxTaxEngine�┌��察�the test code has a valid instance of
ITaxEngine。 It¨s very important to note that the test code has no idea what type implemented
the interface。 This allows the assembly to change which type is referenced in the implementa
tion of CreateSurtaxTaxEngine�┌� without having to inform the caller of the method。
Putting this into the context of the restaurant�察�it means waiters can be replaced。 So if you
repeatedly visit a restaurant and get a waiter called John�察�but one day John gets sick and is not
working�察�you can still order and receive your food from the waitress called Mary。 It would be a
bad idea for a restaurant to depend on a particular server for a particular guest。
Using Default Implementations
In some cases�察�base classes are not necessary。 Sometimes you can create a default implemen
tation that could span multiple subsystems。 In the case of the tax engine�察�an ine is an ine
in Canada�察�an ine in the United States�察�and an ine in Germany。 What varies is how the
ine is treated in each country when calculating taxes。 Another consistency across countries is
that if ine is a capital gain�察�not all of the ine is taxable。
In the case of ine�察�you can create an implementation that would be identical across
different tax engines�察�as follows�此�
´´´´´´´´´´´´´´´´´´´´´´Page 201´´´´´´´´´´´´´´´´´´´´´´´
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 179
NotInheritable Class TaxIne
Implements ITaxIne
Private _amount As Double
Private _taxableRate As Double
Public Sub New��ByVal amount As Double�察�ByVal taxableRate As Double��
_amount = amount
_taxableRate = taxableRate
End Sub
Public ReadOnly Property RealAmount�┌� As Double _
Implements ITaxIne。RealAmount
Get
Return _amount
End Get
End Property
Public ReadOnly Property TaxableAmount�┌� As Double _
Implements ITaxIne。TaxableAmount
Get
Return _amount * _taxableRate
End Get
End Property
End Class
The ITaxIne interface has two properties that are implemented in TaxIne�此�RealAmount
and TaxableAmount。 The values for the two properties are considered read´only and are defined
by the constructor of TaxIne。 The purpose of the constructor is to assign two values and
then consider the object as immutable。 If you wanted to change the values of the ITaxIne
interface�察�you would need to instantiate a new instance of TaxIne。 While it sounds like a pain
to need to instantiate a new instance whenever you want to change the value of the RealAmount and
TaxableAmount properties�察�this approach has some advantages in terms of performance and
resource management。
In the sample code�察�the TaxableAmount property is the result of multiplying the d