Also known as virtual constructor.
A class or framework can't anticipate the kind of objects it must create.
All products implement a common interface:
interface Product {...}
The creator class postpones decisions about what types of products are created by using a virtual constructor/abstract factory method:
abstract class Creator {
//virtual constructor:
abstract Product makeProduct();
// etc.
}
A concrete creator replaces the abstract factory method with a concrete factory method. In this example the details of the concrete product are hidden as a private inner class:
class ConcreteCreator extends Creator {
private class ConcreteProduct
implements Product {...}
Product makeProduct() { return new
ConcreteProduct(); }
}
In C++ template parameters can represent constructors as well as classes, so generic constructors can be used to delay decisions about the types of products to create:
template<typename Product>
class Creator
{
public:
// generic constructor:
Product* makeProduct() { return new
Product(); }
};
In this case there is no need to introduce an abstract Product base class. Here is how a client creates a concrete product:
Creator<ConcreteProduct> creator;
ConcreteProduct* p = creator.makeProduct();
Also called a kit.
An assembly can't anticipate the types of components it uses.
Assume abstract base classes are introduced for a family of related components/products:
class ComponentA {...};
class ComponentB {...};
An abstract factory/kit provides abstract factory methods for each of these components:
class Factory
{
public:
virtual ComponentA* makeComponentA() =
0;
virtual ComponentB* makeComponentB() =
0;
// etc.
};
An assembly constructor can now be parameterized by a factory that makes the necessary components:
class Assembly
{
private:
ComponentA* a;
ComponentB* b;
// etc.
public:
Assembly(Factory* f)
{
a = f->makeComponentA();
b = f->makeComponentB();
// etc.
}
};
We want to separate the construction of an assembly from the construction of its components.
Encapsulate the assembly construction process in a component called the director. Encapsulate the construction of the components in a component called the builder.
Builders are similar to abstract factories. There are two differences. First, the job of building the assembly is given to a component called the Director. Second, the components are created and added to the assembly by the builder.
Here is the abstract base class for all builders:
class Builder
{
protected:
Assembly* a = 0;
public:
virtual void addComponentA() = 0;
virtual void addComponentB() = 0;
// etc.
Assembly* getAssembly() { return a; }
};
A concrete builder instantiates a concrete assembly and implements the methods for building and adding concrete components to this assembly:
class ConcreteBuilder: public Builder
{
private:
class ConcreteComponentA: ComponentA {
... };
class ConcreteComponentB: ComponentB {
... };
class ConcreteAssembly: Assembly { ...
};
public:
ConcreteBuilder(){ a = new
ConcreteAssembly(); }
void addComponentA() { a->add(new
ConcreteComponentA(); }
void addComponentB() { a->add(new
ConcreteComponentB(); }
};
The process for adding components to the assembly is implemented by the director:
class Director
{
public:
void makeAssembly(Builder* b)
{
b->addComponentA();
b->addComponentB();
// etc.
}
};
Here is how a client builds an assembly:
Builder* b = new ConcreteBuilder();
Director d;
d.makeAssembly(b);
Assembly a = b->getAssembly();
Multiple instances of a class may not make sense or may create confusion.
Hide all constructors. Provide a static factory method that returns a pointer to the single instance of the class.
Assume an instance of the Manager class will be responsible for managing all components of an application. Having multiple managers could create confusion, so we hide all of the constructors. Java and C++ classes have a public implicit default constructor (i.e., a parameterless constructor) that must be made explicit and private. C++ classes also have an implicit copy constructor that must be made public.
class Manager
{
private:
static Manager* theManager;
Manager() { ... }
Manager(const Manager& m) { }
~Manager() { }
public:
// factory method:
static Manager* makeManager()
{
if (!theManager) { theManager = new
Manager(); }
return theManager;
}
// etc.
};
Obviously the factory method and the pointer must be made static. In C++ memory must be allocated and initialized for the pointer separately:
Manager* Manager::theManager = 0;
Here is some sample client code:
Manager* m1 = Manager::makeManager();
Manager* m2 = Manager::makeManager(); // m1 == m2
delete m1; // error, destructor can't be called here
m1 = new Manager(); // error, constructor can't be called here
Assume the following function is declared:
void display(Manager m) { ... }
However calling the function isn't allowed:
display(*m1); // error, copy constructor can't be called here
Managers must be passed by reference:
void display(Manager& m) { ... }
A variation of the Singleton is Intern. Assume a class of
class Symbol
{
private:
string name;
Symbol()
// etc.
};
class Intern
{
private:
map<string, Symbol> symbols;
public:
Symbol makeSymbol(string name)
{
map<string, Symbol>::iterator
p;
p = symbols.find(name);
Smart factory methods.
We can't anticipate the types of the objects we wish to create at runtime.
The Prototype Pattern is like the factory method pattern. Instead of an abstract factory method a concrete factory method builds products based on product descriptions such as class names.
The basic idea is simple, although it sounds complicated. A Product base class maintains a static table that associates product descriptions with product prototypes. The factory method merely searches the table for a prototype. It then asks the prototype to clone itself and returns the clone.