Defining extensible factories.
AbstractFactory
usually defines a different operation for each kind of
product it can produce. The kinds of products are encoded in the
operation signatures. Adding a new kind of product requires changing
the
AbstractFactory
interface and all the classes that depend on it.
A more flexible but less safe design is to add a parameter to
operations that create objects. This parameter specifies the kind of
object to be created. It could be a class identifier, an integer, a
string, or anything else that identifies the kind of product. In fact
with this approach,
AbstractFactory
only needs a single ``Make''
operation with a parameter indicating the kind of object to create.
This is the technique used in the Prototype- and the class-based
abstract factories discussed
earlier.
This variation is easier to use in a dynamically typed language like
Smalltalk than in a statically typed language like C++. You can use
it in C++ only when all objects have the same abstract base class or
when the product objects can be safely coerced to the correct type by
the client that requested them. The
implementation section of
Factory Method shows how to implement such parameterized
operations in C++.
But even when no coercion is needed, an inherent problem remains: All
products are returned to the client with the same abstract
interface as given by the return type. The client will not be able to
differentiate or make safe assumptions about the class of a product.
If clients need to perform subclass-specific operations, they won't be
accessible through the abstract interface. Although the client could
perform a downcast (e.g., with dynamic_cast in C++), that's
not always feasible or safe, because the downcast can fail. This is the
classic trade-off for a highly flexible and extensible interface.