4.4.1 Factories

As things stand, classes such as DefaultBinaryOperatorNode can only be instantiated by calling a C function specific to the class that is to be instantiated. Component models typically strive to decouple clients from the classes they instantiate, which makes it possible to instantiate classes without having compile-time knowledge of them. This property is especially useful for scripting languages, as script hosts need to instantiate classes on behalf of scripts they are interpreting, classes they have not been compiled against.

To realize this, a component model implementation needs to provide a means of instantiating classes as part of a runtime system that all users of the component model are linked against. This can take the form of a standard function called using procedural calling conventions, or the form of an object implementing a system-provided interface. In order to instantiate classes, this function or interface operation needs to be given an argument identifying the class to be instantiated. As such, classes must be given runtime names, in the same vein as the runtime names for interfaces presented in this chapter.

Different languages targeting the component model sketched here may use different memory allocation strategies when instantiating objects. DefaultBinaryOperatorNode, for instance, uses the malloc() function, part of the C standard library, to allocate memory for its object instance. As a component model implementation cannot be privy to these details, it delegates the work of instantiating objects to factories (as noted in section 2.2.5). A factory could aptly be represented as an object implementing an interface with only one operation, CreateInstance().

A component model implementation needs to be able to map runtime names of classes to the factories that are capable of instantiating said classes, and as such needs access to a data store that holds this information. In a statically linked system (that is, one that does not support components per se), a data store in this vein would only need to map runtime names to addresses of factory objects. A system supporting true components would instead need to locate the component housing the class to instantiate, and get an appropriate factory from this component.