From "Design Patterns"
🎧 Listen to Summary
Free 10-min PreviewPrototype Pattern
Key Insight
The Prototype pattern specifies the kinds of objects to create using a prototypical instance and creates new objects by copying, or 'cloning', this prototype. This pattern is particularly useful when a system needs to be independent of how its products are created, composed, and represented, or when classes to instantiate are specified at run-time, perhaps through dynamic loading. It also offers an alternative to building a parallel class hierarchy of factories, which can proliferate with Factory Method, and is efficient when instances of a class can have only a few combinations of state, making it more convenient to clone pre-configured prototypes.
A compelling motivation arises in graphical editors, such as one for music scores, where a framework's 'GraphicTool' needs to create application-specific objects like notes and staves without being coupled to their concrete classes. The solution involves parameterizing 'GraphicTool' with a prototype instance of the 'Graphic' subclass it should create. When a new object is needed, the 'GraphicTool' simply asks its prototype to 'Clone' itself. This approach drastically reduces the number of distinct classes required, as one 'GraphicTool' instance can produce a variety of music objects if the 'MusicalNote' prototype is initialized with different bitmaps or durations, allowing new types of notes to be added easily without new classes.
The Prototype pattern shares benefits with Abstract Factory and Builder, notably hiding concrete product classes from clients and enabling clients to work with application-specific classes without modification. Unique advantages include the ability to add and remove products at run-time by registering and unregistering prototypical instances, specifying new objects by varying values of an existing class, and enabling the creation of complex, user-defined structures by cloning composite prototypes. While it reduces subclassing, particularly in languages like C++ where classes are not first-class objects, its main liability is the complexity of correctly implementing the 'Clone' operation for each 'Prototype' subclass, especially when dealing with deep copies, circular references, or existing classes not designed for copying. For example, a 'MazePrototypeFactory' can be initialized with prototype 'Room', 'Wall', and 'Door' objects, cloning and initializing them on demand to build a maze, thereby avoiding direct instantiation or subclassing the factory for each component type.
📚 Continue Your Learning Journey — No Payment Required
Access the complete Design Patterns summary with audio narration, key takeaways, and actionable insights from Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides.