Abstract Factory

See AbstractFactoryPattern.


Question: Can somebody illustrate how it is advantageous to Create objects using a Factory as against directly creating them?

Check this out: http://www.linuxjournal.com/article.php?sid=3687

from the page ...

The dynamic class loading technique provides developers with a great deal of flexibility in their designs. Dynamic class loading is a means of providing extensibility without sacrificing robustness.

In this article, we will design a simple application that defines a single class, a shape class we wish to use in a drawing package. As we shall see, dynamic class loading allows us to provide a smooth extension path through which users of the application can add new types of shapes without needing to modify the original application code.


Question: that "common method signature" can be a stumbling block. What if the objects I might want my AbstractFactory to create need varying kinds of arguments to be properly initialized? e.g.,

 class ChildA
 {
 public:
  ChildA (void);
  action (void);
 }

class ChildB { public: ChildB (int number_of_widgets, const char *owner_name); action (void); }

class ChildC { public: ChildC (const Thing &parent); action (void); }
Suppose these classes are sufficiently similar that you might substitute one for the other at runtime (viz. the call to action()), but not so similar that they can have signature-compatible ctors. Is this a crazy setup? If not, how do you pass ctor arguments to the create_instance method? I'm thinking of packing the arguments into a single string and forcing all runtime-created objects to accept that single string as their ctor argument list, but that has the reek of a CodeSmell.

The string idea is *not* as crazy an idea as it appears at first glance: That's how ODBC does it, for instance. Think of the string (and its format) as a Memento. -- JeffGrigg (MementoPattern)

Or, maybe you could pursue a lowest-common-denominator strategy, and require all interfaces to take in the parameters you need for just one of the implementations? Something like this (please correct my C++, it's really rusty):

 class AbstractFactory
 {
 public:
   getChild (Thing &parent, int number_of_widgets);
 }

class AFactory { public: ChildA getChild (Thing &parent, int number_of_widgets) { return new ChildA(); } }

class BFactory { public: ChildB getChild (Thing &parent, int number_of_widgets) { return new ChildB( number_of_widgets, *parent->name() ); } }

class CFactory { public: ChildC getChild (Thing &parent, int number_of_widgets) { return new ChildC(parent); } }

Such a solution is more verbose, of course.

Your second solution will get smelly if you later find you have another class ChildD that needs to accept a different parameter; a string for example. If ChildE comes along and wants something else again you will be in serious trouble. First solution looks better to me.
Abstract factory methods don't make much sense where descendent classes require explicit creation which differs from that of their ancestor classes, as is often the case in real world situations. And, as was astutely implied earlier, the notion of Abstract Factory methods falls short in that concrete prototypes usually attempt to do too much with too little or too little with too much.

Yes, abstract factory methods are a developmental design consideration for ideal operations. But, they typically add needless and quirky overhead for something that a concrete factory method (FactoryMethod) handles quite nicely.

-- JJDawson

OK, here's a real-world example. There is a financial transaction to value. We wish to value it using market data structures sourced in one of three ways: (1) by direct calls through to a 3rd-party system ("third-passthrough"), (2) by getting underlying data from the 3rd-party system and building interpolation structures from it locally ("third-local"), (3) by getting underlying data from some other source and building interpolation structures from it locally ("direct-local"). The valuation method must be independent of the source: all it knows is, say, it wants a US dollar LIBOR yield curve for 1 May 2004, and that the yield curve object can return a discount factor for any given date.

One deals with this by using an AbstractFactory class: the valuation code queries calls one method on its interface for said yield curve, another for a set of index volatilities, and so on. Depending on the particular implementation of the AbstractFactory, the yield curve may come from any of the three sources above.

Of course, some of these implementations need more information than others. For instance, third-passthrough and third-local need to know how to connect to the 3rd-party system (so need an ipaddress and port number). This information is passed in when the relevant factory instance is constructed. So the valuation data can then do its stuff in blissful ignorance of how the objects are actually constructed.

Now, when you want to check that your data from source X matches the 3rd-party system, you simply switch from one implementation to another. All other code is the same, so you can instrument the calls to log results in a generic fashion. You can, for instance, make a new implementation of your AbstractFactory interface which spits out objects that do the calculations two different ways and check the results against each other.

In general AbstractFactory can be a very useful technique when you are comparing the results from one system/implementation against another. You can even add AbstractFactory over a transitional period, then flatten it out again once the transistion is over and the relevant subsystem has stabilised, if it looks like you won't need the extra abstraction going forward. I have done that myself: HorsesForCourses and all that.

I think the real question is, how does it come to be that the different classes need different things in order to be constructed, and your client code knows what things are used for construction of the subclass it wants, but it doesn't know which subclass it wants (even though only one of them can be constructed from the things on hand)? I mean, there may be legitimate questions, but answering the question in detail should guide towards a solution -- KarlKnechtel

This example has a lot of industry-specific lingo. It could use some sample data and code.


AbstractFactory could also be used to easily swap out certain representations of a data type--e.g., choosing between AVL trees, B-trees, tries, or hashes as a representation of an associative array--while still maintaining the ability to instantiate new instances of that particular representation. If the type doesn't need to be swapped out at runtime, then this method is nearly equivalent to C++'s templates (although one swaps out the type itself, rather than the factory) or SmlNj?'s typed modules, and somewhat analogous to some usages of HaskellLanguage TypeClasses--to implement polymorphic functions over a Monad superclass, one requires an AbstractFactory of some sort to provide the unit method. (Obviously this is from a mostly functional perspective.)


CategoryPatternFactory

EditText of this page (last edited September 8, 2013) or FindPage with title or text search