In my Abstract Factory post, I mentioned that I really don’t like the pattern, and in particular, code like this:

1:static IGUIFactory CreateOsSpecificFactory()

2: {

3:string sysType = ConfigurationSettings.AppSettings["OS_TYPE"];

4:if (sysType == "Win")

5: {

6:returnnew WindowsFactory();

7: }

8:else

9: {

10:returnnew MacFactory();

11: }

12: }

One of the comments mentioned that this might no be ideal, but it is still better than:

1:if(RunningOnWindows)

2: {

3:// code

4: }

5:elseif(RunningOnMac)

6: {

7:// code

8: }

9:elseif(RunningOnLinux)

10: {

11:// code

12: }

And I agree. But I think that, as the comment mentioned, a far better alternative would be using the container. You can do this using:

1: [OperationSystem("Windows")]

2:publicclass WindowsFactory : IGUIFactory

3: {

4: }

5:

6: [OperationSystem("Linux")]

7:publicclass LinuxFactory : IGUIFactory

8: {

9: }

10:

11: [OperationSystem("Mac")]

12:publicclass MacFactory : IGUIFactory

13: {

14: }

15:

Then you just need to wire things through the container. Among other things, this means that we respect the open / closed principle. If we need to support a new system, we can just add a new class, we don’t need to modify code.

Remember, the Go4 book was written in the age of C++. Reflection didn’t exists, and that means that a lot of patterns do by hands things that can happen automatically.

Nitpicker corner: How is changing my IOC configuration different from changing my Factory?

I am totally with you on this though, but IOC Containers are just nice abstract factories and their configuration has to be treated as code too.
If you screw that up you are hosed, same as if you change the factory code when supporting a new OS.

What hinders you then to put the same convention into the Factory? To me an IOC Container is just that - a factory I can reuse.
(If it weren't .NET I'd even recommend that - but since it's quite easy to shoot yourself in the foot with that implementation I'd use a container for my Convention over my own implementation..
But in Ruby for example things look a lot different.. it's a simple "#{os}Factory".constantize.new)

Also think about the convention a bit: Don't you have to implement the convention explicitly somewhere, because if I run the app on a Platform that's not yet supported I surely don't want my IOC Container to just throw up some weird error but rather gracefully tell the user he is running a system that's not supported and exit.

No why should you want 10s of factories.
I just wanted to say that for certain applications and scenarios using a IOC is the way to go, for certain others (or even only parts of an application) it may be beneficial to write a explicit factory.

There have been numerous occasions where I really had to get really intimate with my IOC container to make it construct objects in a certain way I needed them where a Factory could have saved me a lot of "library complexity" while also being a shorter and more readable solution to people who don't know Container X like their front lawn.

Of course I am still sold on the convention based IOC container idea, just sometimes you have exceptions that warrant the use of the pattern.

With so many containers and their idiosyncratic behaviours, those if statements might be the easiest way to show what the system does. Learning about a new container and weird conventions when the system goes down and people are very angry is not that cool.

Ayende, I think you're misunderstanding the gist of the pattern. Abstract Factory, at least as it is described in my reprint of "Design Patterns" from April 2005, does not mandate (or even suggest) the use of a factory factory. It's just about providing an interface (the Abstract Factory) that has many abstract (or overridable) factory methods used to create a family of objects. It decouples the client by the actual object creation, so by implementing the interface multiple times (Concrete Factories), it's easy to swap one family with another.

The design pattern does not talk about how you get the Concrete Factories. Whether you get them from an IoC container, some other object repository, or a factory factory is outside the scope of the pattern.

So, your "far better alternative" is still an implementation of Abstract Factory.

I agree, it is a pig. I usually avoid a container entirely or use whatever one comes with the host application (e.g. Windsor + RSB or TinyIOC + Nancy). But sometimes you get actual requirements like 'it has to run on any OS' or 'we sell all over the world and have to collect the proper taxes.' Then and only then should you pick a container.

Oren,
Are we saying in today's age, with most applications we write, its imperative to use an IOC container to adhere to the Open closed principle? An example I have is, when the business wishes to add another predicate to a popular search, having to modify a (linq) query some where to add another where clause would be violating OCP. But to add another predicate class that simply gets composed with other predicates and applied to the where clause via your popular IOC container means OCP is respected.
Would you go to this length, considering with the former, its more discoverable for the average support dev with one class having all the predicates, and the latter while respecting OCP, requires more fishing around, inspecting interfaces and signatures to see which (predicate) classes have the same interfaces (or attributes), that help them in being registered and composed together in one query?

Afif,
Please don't put words in my mouth.
There is a difference between modifying behavior, and adding behavior.
Adding support for a new thing should require little if any modification of existing code.
Modifying existing behavior (because of a bug or a change in the requirements) is different.

Both approaches still encourage polymorphic code, and seperate creation concerns - which is the intent of the pattern - so i would say i LIKE the pattern, but the default implementation is outdated.

A long time ago there was a article by a guy from Google who claimed that something like 18 of the GOF four patterns were redundant in dynamic languages, and hence they were pretty much a result of statically typed OO languages.

I've used the c# dynamic keyword in a few places to recover and dispatch on type - which i think may make the visitor pattern implementation a lot simpler.

Having only skimmed the above posts i still agree with most of them.
- C++ can use a templates and policy based to create generic factories and abstract factories.
- Adding a new switch inside a factory to return a new class is up for debate as to whether that is ADDING or MODIFYING code. Strictly your modifying an assembly, but your only adding lines of code, and not modifying any existing lines. So i don't think you are really breaking O/C principle there. That said sometimes it's hard to deploy modified dll's and easier to deploy modified configuration - so the type of change can be really important.
- I need to explore the features of IOC containers more but i only use them for statically known dependencies - i.e avoid referencing the container in code specifically if possible. This means you can't use them, or their lovely dependency resolution in more runtime based creation decisions. So i think factories, and the builder pattern still have their place.

Oren - I regularly reference your posts on various topics - keep up the good work and thanks

In tekpub video, you've mentioned, that
"you don't like containers nowadays very much, because they are used to create very deep object hierarchies and you try to make your architecture as shallow as possible." (that may be not a word exact phrase, but I hope it is accurat enough).

May be you could write some day how you fight with deep object hierarchies, because I my code I see that everything is composed from small pieces and it is not possible to create anything anymore without using container, that causes various headaches.