嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及42何蛍
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��
The room groupings are managed by the LightingController class。 An initial implemen
tation of LightingController is as follows�此�
Public Class LightingController
Private _roomGroupings As BaseLinkedListItem = New RoomGrouping�┌�
End Class
When dealing with linked lists�察�you have a problem�此�which is the first element of a list�拭�When
you use arrays�察�an empty list of arrays is an array with no references。 But there is an explicit
array object。 Using the linked list�察�an empty linked list is a list that does not exist。 Thus�察�when
you want to create a list�察�you need a room。 In LightingController�察�the first element is an instance
of RoomGrouping�察�which is not a room grouping�察�but serves as a placeholder。 To insert a room
grouping�察�you could simply use this code�此�
_roomGroupings。Insert��NewRoomGroup�┌���
Without the placeholder�察�you would need to write the following code whenever you
wanted to add an element into the list。
If _roomGroupings Is Nothing Then
_roomGroupings = NewRoomGroup�┌�
Else
_roomGroupings。Insert��NewRoomGroup�┌���
End If
The code that uses the placeholder is shorter and simpler�察�however�察�it also requires a dangling
instance of RoomGrouping that has no real value。 I chose the dangling approach because I am
making the decision that a room grouping with no identifier is the default room grouping。
Adding a Room Grouping
The following code adds a room grouping ��added to the class LightingController��。
Public Function AddRoomGrouping��ByVal description As String�� As Object
Dim grouping As RoomGrouping = New RoomGrouping�┌� _
With �� _
。Description = description�察�_
。Rooms = Nothing
��
_roomGroupings。Insert��grouping��
Return grouping
End Function
´´´´´´´´´´´´´´´´´´´´´´Page 236´´´´´´´´´´´´´´´´´´´´´´´
214 CH AP T E R 8 * L E A R N IN G AB OU T CO M P O N E N TO R IE N T E D AR C HI TE CT U R E
To add a new room grouping�察�you instantiate RoomGrouping�察�assign the data members�察�and
then call the method _roomGroupings。Insert�┌� to insert the new room grouping into the linked list。
Let¨s look at the technique for assigning data members�察�called object initialization。 In
previous examples�察�when an object was instantiated and we wanted to assign default values�察 �
we would create a constructor with the appropriate parameters。 However�察�another way is to instan
tiate the object and define a block that assigns the appropriate data members or properties。 In the
case of RoomGrouping�察�there are two publicly defined data members�此�Description and Rooms�此 �
。Description = description�察�_
。Rooms = Nothing
The Description and Rooms data members have assign access�察�which is important as this
technique only works with properties that are not read´only。 To assign a data member or prop
erty�察�after the object instantiation�察�add the With keyword�察�and then within curly brackets�察�assign
each individual data member using a key/value pair�察�in this form�此�
With �� 。Key1 = value1�察 �Key2 = value2 ��
The key represents the data member property to assign�察�and the value is the data that is
assigned to the data member or property。 In the form example�察�the properties Key1 and Key2
are set。
Another technique of interest in the code to add a room grouping is the definition of a data
handle when passing information�此�
Return grouping
In the implementation of AddRoomGrouping�┌��察�the variable grouping is assigned an
instance of RoomGrouping。 The declaration of the RoomGrouping class limits its scope to the
LibLightingSystem assembly only�察�while the declaration of LightingController is public。 If the
method AddRoomGrouping�┌� had attempted to return an instance of RoomGrouping�察�the piler
would have marked this as an error�察�because the scope is inconsistent。 Assuming for the moment
that you did want to return an instance of RoomGrouping�察�your only solution would be to declare
RoomGrouping as public。 The declaration change is the wrong solution�察�because RoomGrouping is
a class without declared methods ��other than the base class methods�� and has public data
members。 It is a class for a specific purpose and should not be shared。
Declaring RoomGrouping as public is the wrong approach�察�so another solution is needed。
You could add a counter data member to the RoomGrouping declaration and return an Integer
value indicating the RoomGrouping instance you are referring to in the list。 However�察�that would
mean having access to the list somewhere�察�and then needing to iterate to find the appropriate
RoomGrouping instance。
The solution is to declare the method as returning a type Object。 When you use Object�察 �
you are defining that your method is giving you an object instance。 The caller may or may not
know what the instance type is�察�and in the case of AddRoomGrouping�┌��察�it doesn¨t。 But that is fine�察 �
because you�察�as the user�察�will consider the instance as a key that is managed by the class
LightingController。 In technical jargon�察�the object instance is a handle that you hold and pass
to some other ponent that knows what to do with it。 In the example�察�it means giving the
handle to LightingController because it knows that the handle is an instance of RoomGrouping。
´´´´´´´´´´´´´´´´´´´´´´Page 237´´´´´´´´´´´´´´´´´´´´´´´
C H AP TE R 8 * L E AR N IN G AB O U T CO M P O N E N T O R IE N TE D A R CH I TE C TU R E 215
*Note Handles were very popular in the C programming days and were consider pointers to memory。 The
caller did not know what the pointer pointed to�察�but kept using it when interacting with an API。 These days�察 �
handles have lost significance as we have objects�察 �generics�察�and other programming constructs。 However�察�at
times�察�handles are very useful。 They can help you to avoid the problem of having to expose the internal state
of your API�察�while not having to maintain an object hierarchy to watch which objects are being referenced。
Finding a Room Grouping
When a number of room groupings have been added�察�you will want to find a room grouping
with a particular description。 As room groupings are a doubly linked list�察�it means needing to
iterate the list�察�as follows ��added to LightingController���此�
Public Function FindRoomGrouping��ByVal description As String�� As Object
Dim curr As RoomGrouping = _roomGroupings。NextItem
Do While curr IsNot Nothing
If curr。Description。pareTo��description�� = 0 Then
Return curr
End If
curr = TryCast��curr。NextItem�察�RoomGrouping��
Loop
Return Nothing
End Function
In the iteration code�察�the iteration is similar to the code illustrated earlier in the ^Storing a
Collection Using a Linked List ̄ section。 The one difference is that the curr variable is of type
RoomGrouping�察�and because NextItem is of type BaseLinkedListItem�察�a type cast is necessary。
Then an iteration using a While loop is carried out�察�during each iteration�察�a test paring
curr。Description to the parameter description is made。 If an object is found�察�the handle to
the RoomGrouping is returned�察�and if nothing is found�察�Nothing is returned�察�indicating that the
RoomGrouping could not be found。
This method would be used as follows�此�
Dim foundHandle As Object = controller。FindRoomGrouping�─�description;��
Visual Basic has constructs that make it possible to convert the LightingController class
into a class that has array functionality。 The following method in LightingController declares
array´like functionality�察�which is called a default property
Default Public ReadOnly Property Item��ByVal description As String�� As Object
Get
Return FindRoomGrouping��description��
End Get
End Property
A Visual Basic default property is defined like a property�察�except that the property is prefixed
with a Default keyword。 The default property is named Item by convention�察�and this name is
used by all collection classes for consistency。 The implementation of a property is just like
´´´´´´´´´´´´´´´´´´´´´´Page 238´´´´´´´´´´´´´´´´´´´´´´´
216 CH AP T E R 8 * L E A R N IN G AB OU T CO M P O N E N TO R IE N T E D AR C HI TE CT U R E
other properties。 However�察�the default property is unique in that you use it like an array refer
ence。 You could use the default property as follows�此�
Dim foundHandle As Object = controller�─�description;��
In the example�察�the array index is a string and behaves more like a property bag。 However�察 �
if description were of type Integer�察�then the default property would behave like an index。
*Note Default properties are utility´based and best added to classes that manage collections。 In the case
of the LightingController�察�which manages a collection of room groupings�察�use of a default property is
appropriate。
To find a particular room grouping�察�you would use the methods or default property of
LightingController。 However�察�sometimes a user would like to work with all of the room group
ings that are available and iterate over them。
The previous indexer example and the FindRoomGrouping�┌� method returned an object。
When you iterate the room groupings�察�you don¨t want an object�察�because you don¨t know what
the object represents。 If you call the FindRoomGrouping�┌� method and you search based on a
description�察�the object that is returned is cross´referenced with the description。 However�察�if
you iterate using a numeric default property�察�the returned object means nothing to you other
than being associated with a specific index。 What you really want to know is the description of
each object。
You could define a default property with a numeric value�察�as in the following code�察�and
iterate the individual elements to obtain descriptions。
Default Public ReadOnly Property Item��ByVal index As Integer�� As String
Get
。 。 。
End Get
End Property
*Note A type can have multiple default property definitions�察�but each default property definition must have
different array parameters。
Suppose we implemented a numeric default property。 To iterate the individual room
groupings�察�we would need to use the following code。
For c1 As Integer = 0 To controller。Length 1
Dim description As String = controller��c1��
Next
´´´´´´´´´´´´´´´´´´´´´´Page 239´´´´´´´´´´´´´´´´´´´´´´´
C H AP TE R 8 * L E AR N IN G AB O U T CO M P O N E N T O R IE N TE D A R CH I TE C TU R E 217
This iteration code is acceptable and something that we could use�察�but it involves adding
the property Length to the LightingController class。 Another approach is to use For Each�察�as
follows�此�
For Each rg As RoomGrouping In controller。RoomGroupingIterator�┌�
' Do something with the rg
Console。WriteLine��rg。Description��
Next
The For Each syntax is simpler。 It doesn¨t matter that we¨ve lost the information about
which offset is which description�察�because that information is useless。 Remember we are dealing
with a linked list that can change its order however it pleases。 Thus�察�having a numeric identifier
is pletely meaningless。 The only reliable way to find a room grouping is to know its description
or hold a specific index for the collection。
*Note Unless you are absolutely sure that the collection you are manipulating does not move elements
around�察�holding an index as a unique description of the object can be dangerous�察�and potentially could corrupt
the state of an application。 In this chapter�察�I have illustrated two other techniques that can be used to refer
ence a particular object�此�a handle and a default property。
We¨ll e to the RoomGroupingIterator�┌� method in a bit�察�but first we need to see the
enumerable that it returns。
The LightingController class has no For Each functionality built in。 To give it this function
ality�察�you need to create a class that can be enumerated and a class that can be an enumerator�察 �
which is a class that can perform the iteration。 The plete implementation of a class that
can be enumerated for BaseLinkedListItem is as follows ��it is also the enumerator class�察�as
you¨ll see��。
Public Class LinkedListEnumerable
Implements IEnumerable�察�IEnumerator
Private _currNode As BaseLinkedListItem
Private _firstNode As BaseLinkedListItem
Public Sub New��ByVal linkedList As BaseLinkedListItem��
_currNode = linkedList
_firstNode = linkedList
End Sub
Public Function GetEnumerator�┌� As IEnumerator _
Implements IEnumerable。GetEnumerator
Return Me
End Function
´´´´´´´´´´´´´´´´´´´´´´Page 240´´´´´´´´´´´´´´´´´´´´´´´
218 CH AP T E R 8 * L E A R N IN G AB OU T CO M P O N E N TO R IE N T E D AR C HI TE CT U R E
Public ReadOnly Property Current�┌� As Object _
Implements IEnumerator。Current
Get
Return _currNode
End Get
End Property
Public Function MoveNext�┌� As Boolean _
Implements IEnumerator。MoveNext
If _currNode Is Nothing Then
Return False
End If
_currNode = _currNode。NextItem
If _currNode Is Nothing Then
Return False
Else
Return True
End If
End Function
Public Sub Reset�┌� _
Implements IEnumerator。Reset
_currNode =
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��