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 225 Public Function CreatePrivateRoom() As IRoom Return New PrivateRoom() End Function Public Function CreatePublicRoom() As IRoom Return New PublicRoom() End Function End Module The implementation has three methods: CreateBuilding(); CreatePrivateRoom(); and CreatePublicRoom();。 The fact that CreatePrivateRoom() and PrivateRoom() have similar naming is purely coincidental。 The method could just as well have been called CreateNonControlledRoom()。 The CreatePrivateRoom() and CreatePublicRoom() methods are intended to define method identifiers that users can understand。 What is instantiated in the method must return an IRoom instance。 The CreateBuilding() method is a builder method; and it returns a LightingController instance。 It is fine to return a LightingController instance; because it is a globally defined type and can serve as a basis for the builder method。 In the implementation of the builder method; the room groupings and rooms are instantiated and added to the LightingController instance。 This is the work that the builder should save the end user。 Additionally; by providing a builder method; you avoid creating museum structures that have glaring errors in their structures。 ■Note Factory types serve to instantiate types and define builder methods; but can also be used to perform generic structural operations。 Let’s say that in your museum there is a wing; which contains three public rooms and a private room。 You could define a builder method that creates a wing; and the wing is added to an already created building。 The general idea behind the factory type is to avoid errors and centralize repeated instantiations。 Learning More About Private Classes and Object Initialization In this chapter; you learned how to apply interfaces; implementations; and ponents in a kernel…type situation。 This is very much the type of programming that you will encounter as you continue using Visual Basic。 Here; I will provide a few more details about using private classes and initializing objects with nested data types。 Private Classes The RoomGrouping and Room classes are defined in the LibLightingController project and are private to the library。 This is because RoomGrouping and Room are classes only LightingController needs to support its functionality。 The declaration of each class is internal to the assembly; which is good; but it still means that some developers could use the classes within the kernel assembly for their own purposes。 Sometimes that is a desirable feature; sometimes it is not。 …………………………………………………………Page 248…………………………………………………………… 226 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 the case of LightingController; another approach is to declare the classes in the context of LightingController; as follows: Public Class LightingController Private Class RoomGrouping End Class Private Class Room End Class End Class The Room and RoomGrouping classes are declared within the class; and their declarations are Private。 This means that only LightingController can instantiate and use the classes; and there can never be the situation where another class will instantiate the types。 In the case of LightingController; this would have been a better solution。 Private classes are also used in the factory context。 For example; imagine the situation where you don’t ever want anyone but the factory to instantiate a room。 A possible IRoom decla ration and factory could be as follows: Public Module Factory Private Class MyRoom : Implements IRoom End Class Public Function CreateMyRoom() As IRoom Return New MyRoom() End Function End Module In this implementation of MyRoom; you can be sure that only Factory can ever instantiate MyRoom; and you can always be sure that the only way to manipulate MyRoom is through the IRoom interface。 All too often; developers bee lazy and instantiate types within the assembly; and switch to the implementation type whenever the interface does not have the methods or prop erties that they want。 Object Initialization with Nested Data Types In this chapter; you saw how to use object initialization to assign data members in lieu of a constructor。 Object initialization also works using nested data types。 Consider the situation where a type references another type。 Using object initialization; you can instantiate and assign multiple levels of objects。 Suppose you had this source code: Class MyType Private _dataMember As Integer Public Property DataMember() As Integer Get Return _dataMember End Get …………………………………………………………Page 249…………………………………………………………… 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 227 Set (ByVal value as Integer) _dataMember = value End Set End Property End Class Class EmbeddedMyType Private _embedded As MyType Public Property MyTypeProperty() As MyType Get Return _embedded