This section covers advanced Factory Method implementation techniques (parameterized factories, templates, lazy initialization), the complete Prototype pattern for creating objects by cloning prototypical instances, and the beginning of the Singleton pattern for ensuring a class has exactly one instance.
Key Concepts
Parameterized Factory Method: Uses an identifier parameter to determine which product class to instantiate; subclasses can override to swap, extend, or replace product mappings while delegating unhandled cases to the parent via Creator::Create(id)
Lazy Initialization: Defer product creation until first access via an accessor that checks for null, avoiding problems with calling virtual factory methods in constructors (where the ConcreteCreator's override isn't available yet)
Template Factory Method: A C++ template subclass StandardCreator<TheProduct> eliminates the need to subclass Creator for each product — client supplies only the product class
Prototype Pattern Intent: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying (cloning) this prototype
Prototype eliminates parallel class hierarchies: Instead of a Creator hierarchy mirroring the Product hierarchy, you clone registered prototypes — especially valuable in languages where classes aren't first-class objects
Shallow vs. Deep Copy: Cloning prototypes with complex structures usually requires deep copy so clone and original are independent; circular references make this particularly tricky
Prototype Manager: A registry (associative store) that maps keys to prototypes; clients store and retrieve prototypes dynamically at run-time
Clone Initialization: Clone operations can't take varying parameters across prototype classes; use separate Initialize() methods to set clone state after cloning
Singleton Pattern Intent: Ensure a class has only one instance and provide a global point of access to it
Singleton benefits: Controlled access to sole instance, reduced namespace pollution vs. global variables, permits subclassing and variable instance counts
Commands and Syntax
Parameterized Factory Method with parent delegation:
Product* MyCreator::Create(ProductId id) {
if (id == YOURS) return new MyProduct;
if (id == MINE) return new YourProduct;
if (id == THEIRS) return new TheirProduct;
return Creator::Create(id); // delegate unhandled to parent
}
Lazy Initialization (avoid virtual calls in constructor):
Door* Door::Clone() const { return new Door(*this); }
Singleton structure:
class Singleton {
public:
static Singleton* Instance(); // class-level access point
};
Naming convention: MacApp uses Class* DoMakeClass() for factory methods.
Relationships
Factory Method and Abstract Factory: Abstract Factory is often implemented with factory methods; they frequently co-occur
Factory Method and Template Method: Factory methods are usually called within Template Methods (e.g., NewDocument is a template method that calls factory methods)
Prototype vs. Factory Method: Prototype avoids the parallel Creator class hierarchy that Factory Method produces; Prototype doesn't require subclassing Creator but may need an Initialize operation
Prototype vs. Abstract Factory: Competing patterns that can also complement each other — an Abstract Factory can store prototypes from which to clone products
Prototype with Composite and Decorator: Designs heavy in Composite/Decorator often benefit from Prototype (clone complex composed structures)
Singleton vs. global variables: Singleton improves on globals by encapsulating instance control within the class itself
Exam-Relevant Points
Parameterized factory methods should delegate to the parent class for unhandled product IDs (return Creator::Create(id)) — this enables extension without replacing all logic
Never call factory methods in a C++ constructor — the ConcreteCreator's virtual override isn't available yet; use lazy initialization instead
In Smalltalk, the factory method is the method that returns the class (e.g., documentClass), not the method that creates the instance — the class object itself acts as the prototype
Prototype pattern is most useful in static languages (C++) where classes aren't first-class objects; less important in Smalltalk/Objective-C where class objects already serve as prototypes
Deep copy is required when prototypes have complex structures and the clone must be independent of the original
The main liability of Prototype: every subclass must implement Clone, which is difficult when classes already exist, have circular references, or contain non-copyable objects
Clone's return type can be the base class (e.g., Wall*) even when returning a subclass pointer — clients shouldn't need to downcast
Singleton ensures one instance with controlled access; the class itself is responsible for tracking its sole instance
Singleton permits subclassing — you can configure which subclass instance to use at run-time without client code changes
Known uses of Prototype: Sutherland's Sketchpad (first example), ThingLab (first in OO language), ET++ framework (dynamic class loading via prototype registry)