友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
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 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!