嗔秤戻幣�哉膵�云利匈嬉蝕湊蛸賜�塋床四衲���萩晦編報炎嘔囚^泡仟 ̄云利匈��
VB2008貫秘壇欺娼宥(PDF鯉塀哂猟井)-及43何蛍
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何! 泌惚云慕短嗤堋響頼���誅卒亮茂�俊彭堋響��辛聞喘貧圭 "辺茄欺厘議箝誓匂" 孔嬬 才 "紗秘慕禰" 孔嬬��
End Function
Public Sub Reset�┌� _
Implements IEnumerator。Reset
_currNode = _firstNode
End Sub
End Class
A class that can be enumerated must fulfill two objectives�此�implement the IEnumerable
interface and implement the IEnumerator interface。 The IEnumerable class has a single method�察 �
GetEnumerator�┌��察�which is used to retrieve a class instance that implements the IEnumerator
interface。 The two interfaces are split because retrieving the iteration functionality and iter
ating the collection are two separate steps。 However�察�in the case of LinkedListEnumerable�察 �
these steps are bined into one class�察�and that is often the case。
The best way to explain how LinkedListEnumerable works is to go through the code and
explain what methods and properties are called。
1。 The code in the client application starts a For Each loop�察�and sets up a context where a
collection of elements is being iterated。
2。 The code calls the collection iterator。 In the example�察�this means calling the method
RoomGroupingIterator�┌�。
3。 RoomGroupingIterator�┌� returns an instance of LinkedListEnumerable�察�which is assigned
the linked list that will be iterated。
Public Function RoomGroupingIterator�┌� As IEnumerable
Return New LinkedListEnumerable��_roomGroupings��
End Function
´´´´´´´´´´´´´´´´´´´´´´Page 241´´´´´´´´´´´´´´´´´´´´´´´
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 219
4。 The method LinkedListEnumerable。GetEnumerator�┌� is called�察�and an instance of
IEnumerator is returned。
5。 The code calls the method LinkedListEnumerable。MoveNext�┌�。
6。 The implementation of MoveNext�┌� returns True to indicate that it was possible to move
to the next element。 If False is returned�察�it means that the end of the collection!or in
this case�察�the linked list!is reached。
7。 If MoveNext�┌� returns True�察�then the property LinkedListEnumerable。Current�┌� is called
to retrieve the current linked list element。
8。 The retrieved linked list element is assigned to the variable of the For Each loop�察�which
is rg in this example。
9。 Control is returned to the For Each loop�察�and the user code does something with the
linked list element。
10。 When the For Each loop attempts another iteration�察�steps 5 through 9 are repeated until
MoveNext�┌� returns False。
11。 When MoveNext�┌� returns False�察�the iterator exits�察�causing an exit of the For Each loop。
Adding Rooms to Groupings
The data handle that we defined when adding the grouping is used when we add a room to a
grouping。 The idea of the handle is to provide a reference that the kernel can use。 Since the
handle is an instance of a RoomGrouping type�察�whenever a room is added to a grouping based on
a handle�察�it is not necessary to find the room grouping。 The handle is the room grouping�察�and
all that is necessary is a type cast。 The following demonstrates how to add a room to a room
grouping ��in LightingController��。
Public Sub AddRoomToGrouping��ByVal grouping As Object�察�ByVal room As IRoom��
Dim roomGrouping As RoomGrouping = TryCast��grouping�察�RoomGrouping��
If roomGrouping Is Nothing Then
Throw New Exception�─�_
;Handle grouping is not a valid room grouping instance;��
End If
Dim oldRooms As Room = TryCast��roomGrouping。Rooms�察�Room��
If oldRooms Is Nothing Then
roomGrouping。Rooms = New Room�┌� With ��。ObjRoom = room��
Else
roomGrouping。Rooms。Insert��New Room�┌� With ��。ObjRoom = room����
End If
End Sub
In the implementation of AddRoomToGrouping�┌��察�the first step is to cast the handle grouping
to an instance of RoomGrouping。 The cast used is the TryCast�┌� function�察�so that if the cast fails�察 �
it is only necessary to test if roomGrouping is not Nothing。 Executing the Nothing test is absolutely
vital�察�otherwise�察�you might perform operations that will cause an exception to be thrown。
´´´´´´´´´´´´´´´´´´´´´´Page 242´´´´´´´´´´´´´´´´´´´´´´´
220 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
Once the handle has been cast to a RoomGrouping instance�察�adding a room to the linked list
is trivial。 Adding a room involves only assigning the head of the list if there are no rooms in the
list�察�or calling the method Insert�┌� if there are rooms。
Performing Operations on a Group
With a grouping defined�察�you can perform global operations that affect all rooms of a grouping。
One example is turning off the lights in all the rooms in a grouping�察�which is based on the IRoom
interface instance。 Here is the code to turn off all of the lights in a grouping�此�
Public Sub TurnOffLights��ByVal grouping As Object��
Dim enumerableGrouping As LinkedListEnumerable = _
New LinkedListEnumerable��TryCast��grouping�察�BaseLinkedListItem����
For Each room As IRoom In enumerableGrouping
Dim remote As IRemoteControlRoom = TryCast��room�察�IRemoteControlRoom��
Dim sensorRoom As ISensorRoom = TryCast��room�察�ISensorRoom��
If sensorRoom IsNot Nothing Then
If Not sensorRoom。IsPersonInRoom Then
Continue For
End If
ElseIf remote IsNot Nothing Then
remote。LightSwitch��False��
End If
Next
End Sub
Notice that the handle is not converted into a RoomGrouping instance。 The handle is type
cast to BaseLinkedListItem�察�and then passed to the LinkedListEnumerable constructor。 For each
iteration of the For Each loop�察�the IRoom instance room is cast into the types IRemoteControlRoom
and ISensorRoom。 A cast to both of these types is necessary because�察�depending on the room
type�察�certain algorithms need to be executed。 For example�察�if the room is of type ISensorRoom
and the property IsPersonInRoom is True�察�then the lights should be left as is。 If the lights are to
be left as is�察�that means performing the next iteration using the Continue For keywords。
If the processing continues�察�we check if the room can be remotely controlled�察�which means
it implements the interface IRemoteControlRoom。 If remote is not Nothing�察�then we can call the
LightSwitch�┌� method with a parameter of False to turn off the lights。 The iteration continues
for all rooms in the grouping。
This pletes the kernel�察�but before you how it fits with a lighting application�察�I would
like to discuss an alternative approach to implementing the kernel。
Defining the Kernel As an Interface Instead of a Class
As I noted earlier�察�rather than defining the kernel as a class�察�another approach would be to define
the kernel as an interface that is implemented。 If a pany were to distribute multiple implemen
tations of a controller�察�an interface would be appropriate�察�but only if the multiple implementations
of the interface used the same set of methods。
´´´´´´´´´´´´´´´´´´´´´´Page 243´´´´´´´´´´´´´´´´´´´´´´´
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 221
Do not confuse multiple implementations with multiple implementations that offer a
pletely different feature set。 For example�察�controller version 1 and controller version super
duper 1000 might control the same room types�察�but the inputs�察�outputs�察�logic�察�and algorithms
contained in each might be pletely different。 In that case�察�using an interface gains no advan
tage。 You might use a version 1 interface on a version super´duper 1000 for legacy integration�察 �
since the old interface has older ideas。
You would use an interface for the controller when multiple controllers implement the
same interface。 You would use an interface if you want the flexibility to later implement multiple
implementations using the same interface。 On the other hand�察�if there will only ever be a single
implementation for a single interface declaration�察�it¨s much easier to use a class declared as
Public。
If you do decide to declare the controller using an interface and implementation�察�you need
to structure the project differently than the organization used for this chapter¨s example。 The
reason is that you cannot declare the interfaces and implementations in the same project。
Imagine trying to offer multiple kernel implementations�察�but for the users to be able to use the
interfaces�察�they must reference a project that contains a particular kernel implementation。
You will need to modularize the structure and have an organization similar to that shown
in Figure 8´5。
Figure 8´5。 Organization of a modular interface and implementation architecture
´´´´´´´´´´´´´´´´´´´´´´Page 244´´´´´´´´´´´´´´´´´´´´´´´
222 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
In Figure 8´5�察�the individual boxes represent a single assembly。 Each assembly serves
a unique purpose�此�
o Definitions�此�An assembly that contains all interfaces used by all of the other assemblies。
This represents a single assembly that changes very rarely and is a cornerstone of the
application。 Along with interfaces�察�you would add general utility classes that all assem
blies would reference。
o User�此�The main application that interacts with the interfaces of objects that are imple
mented in either the Kernel or Implementations assemblies。 The User assembly is
responsible for wiring together all of the types。
o Kernel�此�An assembly that defines the main functionality of the application and manipu
lates instances that implement interfaces from the Definitions assembly。 The kernel
does not know where the interfaces are implemented�察�and it expects some other piece of
code to know where the implementations are。
o Implementations�此�An assembly that contains the implementations of the interfaces that
the kernel manipulates。 The programmer may create a single implementation assembly
or multiple assemblies。 The implementations are only aware of the Definitions assembly�察 �
they are unaware of the Kernel assembly。
Building a plete Application
All of the code illustrated thus far is related to the kernel�察�and it would seem that our applica
tion is plete。 In reality�察�the kernel has done nothing other than organize and manipulate
the rooms。 The kernel has not defined any implementations for a particular room。 Now let¨s
see how to define some rooms and use the rooms in the context of the kernel。
The idea is to enable a developer to add functionality to the kernel without affecting the
code of the kernel。 The example that we will go through defines a couple of rooms in a museum
��the Museum project��。
*Note The implementation of the Home project is not discussed here�察�but it is available in this book¨s down
loadable source code。
Defining Some Rooms
The rooms are defined in a separate assembly called Museum and are not part of the kernel。 The
following is an example of a room implementation。 Again�察�remember to include a reference to
LibLightingSystem ��right´click References in Museum and select Add Reference then Projects
LibLightingSystem��。
´´´´´´´´´´´´´´´´´´´´´´Page 245´´´´´´´´´´´´´´´´´´´´´´´
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 223
。 。 。
Imports LibLightingSystem
Friend Class PrivateRoom �此�Implements INoRemoteControlRoom
End Class
Friend Class PublicRoom �此�Implements ISensorRoom
Public ReadOnly Property IsPersonInRoom�┌� As Boolean _
Implements ISensorRoom。IsPersonInRoom
Get
Return False
End Get
End Property
Private _lightLevel As Double
Public ReadOnly Property LightLevel�┌� As Double _
Implements ISensorRoom。LightLevel
Get
Return _lightLevel
End Get
End Property
Public Sub LightSwitch��ByVal lightState As Boolean�� _
Implements IRemoteControlRoom。LightSwitch
If lightState Then
_lightLevel = 1
Else
_lightLevel = 0
End If
End Sub
Public Sub DimLight��ByVal level As Double�� _
Implements IRemoteControlRoom。DimLight
_lightLevel = level
End Sub
End Class
The two room declarations�察�PrivateRoom and PublicRoom�察�are both internal to the assembly。
Each room implements the interface that it deems appropriate。 PrivateRoom implements the
interface INoRemoteControlRoom�察�indicating that LightingController should leave the room alone。
PublicRoom implements ISensorRoom�察�indicating that it will tell the controller when a person is
in the room and allow itself to be controlled。 The implementation of PublicRoom is trivial and
frankly not that useful�察�but it illustrates the bare minimum of what needs to be implemented。
In a production environment�察�PublicRoom would have access to external devices such as a
heat sensor and lights。 The objective of PublicRoom would be to give and take signals from the
LightingController and take action。 It is not up to PublicRoom to ask whether or not a decision
´´´´´´´´´´´´´´´´´´´´
酔楯荷恬: 梓囚徒貧圭�鮗� ○ 賜 ★ 辛酔堀貧和鍬匈 梓囚徒貧議 Enter 囚辛指欺云慕朕村匈 梓囚徒貧圭�鮗� ● 辛指欺云匈競何!
梁椣戻幣�� 梁心弌傍議揖扮窟燕得胎��傍竃徭失議心隈才凪万弌誌育断蛍�輌臆惨軼僑〃�燕慕得珊辛參資誼持蛍才将刮襲潜��範寔亟圻幹慕得 瓜寡追葎娼得辛參資誼寄楚署衛、持蛍才将刮襲潜填��