Ian said:
From wherever you would get the information required to instantiate and
object from an Abstract Factory. It's just a different way of achieving
the same end.
No it's not. Putting the class-name in a string doesn't buy you
anything[1], since you still have to relate the objects to types that
may vary from one instantiation to the next. There are two separate
concerns here: What concepts need to be fulfilled, and which types
should fulfill them. The abstract factory handles the latter concern on
a per-instantiation basis.
Suppose you have an immutable 'rectangle' type. Client code creates
rectangles by requesting them from an abstract factory. Ordinarily,
each rectangle must store both its width and height. If the width and
height of such an immutable rectangle happen to be the same, a simpler
representation may be possible; figuring this out is the factory's job.
The client (pseudo-)code looks like this:
AbstractRectangle rect = abstractFactory->createRectangle(w, h);
The client code need neither know nor care what concrete type implements
the rectangle. This is the point of the Factory design pattern. It
gives you more flexibility than a single class-name per type.
The point of Abstract Factory is that not only can the client code be
isolated from concrete product types, but even from the concrete factory
type. It has exactly one more level of indirection.
You can mix the product-creation code together with product-use code in
C++, Python, or the language of your choice, but you'll just get muddled
code.
[1] If you are just trying to parameterize some existing object creation
code, a Python string might be OK as a ConcreteBuilder in the Builder
pattern; however, the interface certainly leaves something to be
desired. I personally would prefer the string at least be wrapped in a
dedicated type implementing a properly designed AbstractBuilder
interface, rather than just "whatever interface strings happen to support."