I'm finding myself getting a bit muddled by these two patterns while reading DesignPatternsBook.
Both classes have abstract classes (Abstract Factory, Abstract Product in Abstract Factory & Abstract Creator and Abstract Product in Factory Method). Both have subclasses that customize the classes for specific use - (Concrete Factory, Concrete Product, Concrete Creator, Concrete Product).
So what's the difference between Factory and Creator? Both
The Factory knows WHAT to create and gets its instructions on WHEN from another object (Instruction through ObjectComposition?)
The Creator knows WHAT to create and has a shared method that tells it WHEN to create another object. (Instruction through Inheritance)
But the book also says Abstract Factory is often implemented with factory methods. So perhaps WHEN is not important.. and I'm missing something obvious here.
So:
Is FactoryMethodPattern simply: Each subclass knows what other classes to use/objects to create.
AbstractFactoryPattern is: Swapping FactoryMethod Classes with Object Composition
With FactoryMethodPattern, the method is in the object that uses it. With AbstractFactoryPattern, it's moved to a separate factory object. It's the difference between "Foo foo = this.createFoo();" and "Foo foo = factory.createFoo();" -- JasonArhart
In my understanding, the difference between FactoryMethod and AbstractFactory is similar to the one between TemplateMethod and the StrategyPattern - the former uses inheritance to get the concrete implementation, the latter composition. -- Anonomyous Genius
FactoryMethod is a basic pattern. It is always used when you work with the AbstractFactory pattern. The AbstractFactory adds two ideas to the idea of the FactoryMethod:
I've read GangOfFour's DesignPatternsBook among others, but their explanations are often kinda vague. The HeadFirstDesignPatterns Book has an excellent section devoted to this very topic. I suggest you refer to it. Here's how I understand the difference between AbstractFactorys and FactoryMethods (using the JavaLanguage):
For the examples: I'm writing a program that could use several different implementations of a ResourceDescriptionFramework Database. I don't want to tie the program to any particular implementation. Two different implementations are JenaDatabase and SesameDatabase classes. Each implementation is an adapter (see AdapterPattern and StrategyPattern) around the third-party databases (Jena and Sesame respectively). Each class also implements the RdfDatabase interface. Here's a diagram:
RdfDatabase ^ | | +-- JenaDatabase --uses---------------> Jena | | +-- SesameDatabase --uses-------------> SesameHere's some code explaining their relationship:
public interface RdfDatabase {} public class Jena''Database implements RdfDatabase {} public class SesameDatabase implements RdfDatabase {}Here's the problem: I've also got a client of RdfDatabase that needs a concrete implementation to work with (i.e., to search for something in the database). I shouldn't do this, since every time I switch implementations of RdfDatabase I need to edit the source of a big file and recompile it:
public class BadClient { public Map queryDatabase(String queryString) { private RdfDatabase db = new JenaDatabase(); checkQueryIsValid(queryString); return db.find(queryString); } }Here's how a FactoryMethodPattern solves the problem: Basically, a Factory Method is like a Template (see TemplatePattern) with the implementation of the method that creates the object left to subclasses. Say
public abstract class TemplateClient { public Map queryDatabase(String queryString) { RdfDatabase db = databaseFactory(); checkQueryIsValid(queryString); return db.find(queryString); } public abstract RdfDatabase databaseFactory(); }Note: Normally I'd call the factory method "createDatabase" or something like that. I simply labelled it databaseFactory to indicate that the factory method is that particular method.
Now, in order to use the TemplateClient, I need to subclass it and provide the implementation of the appropriate database. If I needed Jena, I could use:
public class JenaClient extends TemplateClient { public RdfDatabase databaseFactory() { return new JenaDatabase(); } }This localizes where the decision is made on which database to use. I don't risk making a mistake or introducing bugs into code unrelated to creating databases since it is in a different class (i.e., TemplateClient). Here's a diagram of how everything fits using the original names:
AbstractCreator --uses--------------> AbstractProduct ^^ || || ConcreteCreator --creates-----------> ConcreteProductThat's how the FactoryMethod pattern works.
Here's a different, unrelated problem: In the previous case, there was only a single class being used by the AbstractCreator. But what if there were twenty classes being created? Say those twenty classes were highly coupled and depended on each other. A programmer who extends AbstractCreator would have to write twenty factory methods to keep up, and that CodeSmells.
Even with only a few (highly-coupled) classes, an inexperienced programmer could write methods that use two incompatible implementations. Here's an example of this problem: Instead of a single RdfDatabase, you also needed an RdfWriter that used a particular engine:
RdfDatabase ^^ || || U+-- JenaDatabase --uses---------------> Jena S| E| S+-- SesameDatabase --uses-------------> Sesame | | RdfWriter ^ | | +-- JenaWriter --uses-----------------> Jena | | +-- SesameWriter --uses---------------> SesameA concrete client that implements an abstract class which uses the factory method doesn't protect mistakes like:
public abstract class BadTemplate2Client { public Map writeDatabase() { RdfDatabase db = databaseFactory(); RdfWriter ww = writerFactory(); return ww.doSomethingWith(db); } public RdfDatabase databaseFactory(); public RdfWriter writerFactory(); } public class BadJena2Client extends BadTemplate2Client { public RdfDatabase databaseFactory() { return new JenaDatabase(); } public RdfWriter writerFactory() { return new SesameWriter(); } }Whoops! That could cause lots of runtime problems if SesameWriter can't be used with JenaDatabase. However, this will compile without an error message.
Here's how the AbstractFactoryPattern solves this. It is a single class that just makes the highly-coupled classes:
public abstract class RdfFactory { public RdfDatabase databaseFactory(); public RdfWriter writerFactory(); }Now that looks a lot like the bad code. However, there is a subtle improvement. You see, the programmer who writes implementations of the highly-coupled classes (JenaDatabase and JenaWriter, for instance) usually isn't writing the client which uses them. The highly-coupled classes form a framework which other client-programmers use. Well, the framework-programmer (don't confuse with the client-programmer) will write the factory class that contains the FactoryMethods for each of class in the framework. Here's a revised client:
public abstract class Template2Client { public Map writeDatabase() { RdfFactory factory = createRdfFactory(); RdfDatabase db = factory.databaseFactory(); RdfWriter ww = factory.writerFactory(); return ww.doSomethingWith(db); } public RdfFactory createRdfFactory(); } public class Jena2Client extends Template2Client { public RdfFactory createRdfFactory() { return new JenaFactory(); } }Notice: I used a factory-method to choose the factory-class to use (I named it createRdfFactory to avoid confusion with the alternative, RdfFactoryFactory). The following uses just the AbstractFactoryPattern, but is a less-flexible design:
public class Jena3Client { public Map writeDatabase() { RdfFactory factory = new JenaFactory(); RdfDatabase db = factory.databaseFactory(); RdfWriter ww = factory.writerFactory(); return ww.doSomethingWith(db); } }Also note that the factory-class uses factory-methods to create each individual object. The functions databaseFactory() and writerFactory() are factory-methods. Factory-classes could use different ways to create each object (like using a PrototypePattern), but factory-methods are most common.
Hope that helps! -- JimmyCerra
What if Jena2Client is implemented as:
public class Jena2Client extends Template2Client { public RdfFactory createRdfFactory() { return new SesameFactory(); } }Wont we have the same problem which you have tried to avoid by using AbstractFactory?
No, the problem in my example was that incompatible classes are created. Neither my implementation nor your implementation makes that mistake. Design-wise, there is no problem with your implementation!
The problem in your 'Jena2Client' class is that is really a Sesame Client, just poorly named. I could have named my implementation:
public class MyClient extends Template2Client { public RdfFactory createRdfFactory() { return new JenaFactory(); } }Your client could be written with:
public class YourClient extends Template2Client { public RdfFactory createRdfFactory() { return new SesemeFactory(); } }As you can see, the factory method makes it is easy to switch abstract RdfFactory implementations. (Note that there are other ways of accessing Factories as well - many use StaticFactory idioms in the abstract class, but I don't like that method.)-- JimmyCerra
That's a nice example. We can say that an AbstractFactory provides an interface for a collection of Factory methods and also provides a mechanism for the creation of concrete factories. -- Shakir
Thanks. The intent of an AbstractFactory is simply to provide an interface for a creating a set of related, possibly interdependent objects. Although an AbstractFactory often uses FactoryMethods - as the above example does - they are not limited to them. Alternatives include (but are not limited to) Abstract Factories that use:
See also: AbstractFactory, FactoryMethod, PrototypePattern