While preparing a session on (object-oriented) object creation for my Advanced Design and Programming course, I noticed that there are at least two major ways of looking at how to decide on how to create an object. The traditional way is a (still unwritten) pattern language that utilizes the classic Gang-of-Four object creational patterns (and then some) to guide the developer in designing the object creation process.
Fortunately, object creation has a neatly defined design space with clearly independent dimensions and hence lends itself well to a structured discussion. Without further ado, here are the dimensions of this design space as I see them:
- Delegation. Who gets to create the object? Options are: on-the-spot, this-object, separate-object
- Selection. How is the concrete class selected? Options are: on-the-spot, by-switch-case, by-subclassing, by-colocating, by-mapping
- Configuration. How is a class mapping configured? Options are: in-code, by-annotation, by-configuration-file
- Instantiation. How is the concrete class instantiated? Options are: in-code, by-class-object, by-prototype, by-function-object
- Initialization. How is the new object initialized? Options are: default, by-cloning, by-fixed-signature, by-key-value-pairs, in-second-step
- Building. How is the object structure built? Options are: default, by-cloning, by-building
Using this design space, a developer can tailor a solution to the specific design situation at hand. Which options are chosen from the table for which dimension typically follows from the desired flexibility. As always, simpler is better, unless it is too simple.
It is also worth noting that design patterns cover a subspace of the overall design space. For example, the Factory Method pattern uses this-object delegation, by-subclassing selection, says nothing about configuration, in-code instantiation, any initialization, and says nothing about building.
The following table shows the relationship between some well-known design patterns and the choices they codify.
I think a pattern language is still warranted for some design decisions, actually most design decisions, perhaps, if the design space is sparsely populated with viable options. This is not the case with object creation: The design dimensions are almost completely orthogonal, allowing for a pick-and-choose approach. There simply aren’t too many constraints that reduce the options in this design space.