Ayende @ Rahien

Hi!
My name is Oren Eini
Founder of Hibernating Rhinos LTD and RavenDB.
You can reach me by phone or email:

ayende@ayende.com

+972 52-548-6969

, @ Q c

Posts: 18 | Comments: 66

filter by tags archive

Design patterns in the test of timeAbstract Factory

time to read 5 min | 901 words

The essence of the Abstract Factory method Pattern is to "Provide an interface for creating families of related or dependent objects without specifying their concrete classes".

More about this pattern.

Here is some sample code:

   1: static IGUIFactory CreateOsSpecificFactory()
   2: {
   3:     string sysType = ConfigurationSettings.AppSettings["OS_TYPE"];
   4:     if (sysType == "Win") 
   5:     {
   6:         return new WindowsFactory();
   7:     } 
   8:     else 
   9:     {
  10:         return new MacFactory();
  11:     }
  12: }

I am in two minds about this pattern. On the one hand, we have pretty damning evidence that this has been really bad for the industry at large. For details, you can see Why I Hate Frameworks post. When I first saw that, just shortly after reading the Go4 for the first time, I was in tears from laughing. But the situation he describe is true, accurate and still painful today.

Case in point, WCF suffers from a serious overuse of abstract factories. For example, IInstanceProvider (and I just love that in order to wire that in you usually have to implement IServiceBehavior).

As the I Hate Frameworks post mentioned:

Each hammer factory factory is built for you by the top experts in the hammer factory factory business, so you don't need to worry about all the details that go into building a factory.

Awesome, or not, as the case may be.

Then again, it is a useful pattern. The problem is that in the general case, creating objects that create objects (that create even more objects) is a pretty good indication that your architecture is already pretty hosed.  You should strive to an architecture that has minimal amount of levels, and an abstract factory is a whole new level even on its own.

Recommendation: Avoid if you can. If you run into a place where you think that needs this, consider if you can simplify your architecture to the point where this is not required.

More posts in "Design patterns in the test of time" series:

  1. (21 Jan 2013) Mediator
  2. (18 Jan 2013) Iterator
  3. (17 Jan 2013) Interpreter
  4. (21 Nov 2012) Command, Redux
  5. (19 Nov 2012) Command
  6. (16 Nov 2012) Chain of responsibility
  7. (15 Nov 2012) Proxy
  8. (14 Nov 2012) Flyweight
  9. (09 Nov 2012) Façade
  10. (07 Nov 2012) Decorator
  11. (05 Nov 2012) Composite
  12. (02 Nov 2012) Bridge
  13. (01 Nov 2012) Adapter
  14. (31 Oct 2012) Singleton
  15. (29 Oct 2012) Prototype
  16. (26 Oct 2012) Factory Method
  17. (25 Oct 2012) Builder
  18. (24 Oct 2012) A modern alternative to Abstract Factory–filtered dependencies
  19. (23 Oct 2012) Abstract Factory

Comments

tobi

I think WCF would have been well off using the ASP.NET MVC filter model. WCF actions are very similar to REST endpoints.

Pop Catalin

Still better than:

if Windows

...

elseif Mac

...

However what I've come to like allo more than abstract factories is a plugin architecture combined with a boostrapper reponsible for dynamically loading pluggins.

This way you can centralize and isolate your specific features in separate plugins, withouth having to deal with the mess of working with factory factories.

Philip Nelson

Well, yes. It does seem to point at a conflict though, and too may layers is the inevitable result. The old adage, that all problems in computer science can be solved with another layer of indirection, results in things like Abstract Pattern where you point at places in your architecture and say that all things must pass through here. What you need is a good way to say, you must pass though here when you need to, and otherwise, not so much.

slava

I think in general Factory pattern is just OOP alternative to Functional curry if you will.

Intuition would be to think about this pattern (or curry in OOP) as a process to shape object. You have some formless object (wrapped in factory pattern), you give it more specs and it starts to shape itself, and you can continue to shape it until you satisfied and it fits your needs.

Bertrand Le Roy

Any thoughts about how abstract factory relates to dependency injection?

Steve Py

My favourite flavour of abstract factories are when someone gets the idea to abstract something like an ORM/DAL, then proceed to create an abstract factory that only has one construction option with a comment that they may want to support "X" in the future. YAGNTDAF! (ya ain't gonna need that damned abstract factory)

Rafal

Java hasn't changed that much since Joel's post. They have added a few factory factories to the standard. For example, an ORM factory [JPA] - Steve, you'll like it.

Michael

Instead of checking the OS_TYPE, I would let the Installer decide which is the correct Type to use, configure the type where Autofac (or whatever Inversion of Control Container you use) can map it to IGUI Factory.

Ed Blackburn

I agree, implementing this pattern is a degree of last-resort. It has certainly been superseded (and just as abused by Containers).

Personally I'm not a fan of switch statements - a popular hacky alternative for object creation.

For simple abstract factories I've followed this approach:

internal abstract class Widget
{
    internal static Widget Create()
    {
        var map = new Dictionary<PlatformID, Func<Widget>>
                      {
                          {PlatformID.Win32Windows, () => new Windows()},
                          {PlatformID.MacOSX, ()=> new Mac()}
                      };

        return map[Environment.OSVersion.Platform]();
    }

    internal abstract void Action();
}

internal class Windows : Widget
{
    internal override void Action() { }
}

internal class Mac : Widget
{
    internal override void Action() { }
}
João P. Bragança

@Ed Blackburn,

That IS a container, it's just far far simpler than the ones you see out there. :) As long as Widget has no dependencies this is the way to go IMO.

Comment preview

Comments have been closed on this topic.

FUTURE POSTS

  1. RavenDB 3.0 New Stable Release - one day from now
  2. Production postmortem: The industry at large - about one day from now
  3. The insidious cost of allocations - 3 days from now
  4. Buffer allocation strategies: A possible solution - 6 days from now
  5. Buffer allocation strategies: Explaining the solution - 7 days from now

And 3 more posts are pending...

There are posts all the way to Sep 11, 2015

RECENT SERIES

  1. Find the bug (5):
    20 Apr 2011 - Why do I get a Null Reference Exception?
  2. Production postmortem (10):
    01 Sep 2015 - The case of the lying configuration file
  3. What is new in RavenDB 3.5 (7):
    12 Aug 2015 - Monitoring support
  4. Career planning (6):
    24 Jul 2015 - The immortal choices aren't
View all series

Syndication

Main feed Feed Stats
Comments feed   Comments Feed Stats