When is factory method better than simple factory and vice versa?
Working my way through the Head First Design Patterns book.
I believe I understand the simple factory and the factory method, but I'm having trouble seeing what advantages factory method brings over simple factory.
If an object A uses a simple factory to create its B objects, then clients can create it like this:
A a = new A(new BFactory());
whereas if an object uses a factory method, a client can create it like this:
A a = new ConcreteA(); // ConcreteA contains a method for instantiating
// the same Bs that the BFactory above creates, with
// the method hardwired into the subclass of A, ConcreteA.
So in the case of the simple factory, clients compose A with a B factory, whereas with the factory method, the client chooses the appropriate subclass for the types of B it wants.
There really doesn't seem to be much to choose between them. Either you have to choose which BFactory you want to compose A with, or you have to choose the right subclass of A to give you the Bs.
Under what circumstances is one better than the other?
Thanks all!
Edit: Adding a little to the confusion IMO is the explanation given in the Head First narrative where they transition from simple factory to factory method by saying (p.119) "franchises were using your [simple] factory to create pizzas, but star开发者_如何学运维ting to employ their own home-grown procedures for the rest of the process: they'd bake things a little differently.." and they have that picture of a chef who apparently did something disgusting to his pizzas.
But there's nothing about using a simple factory that gives clients access to the bake() method or any of the other parts of the process. And there's nothing about using a factory method that would help if there were any problem with it.
So it looks to me like the reason Head First imply for using a factory method over a simple factory is bogus..
Analyse the differences in terms of different roles: users of A and providers of A. The patterns have different implications for these roles, these are significant as things change over time.
In the case of
A myA = new SomeConcreteA()
the clients of A know nothing about the fact that Bs even exist. The choice of a particular concrete A might be influenced by some documentation that it uses particular Bs or some completely other features of the A family. The providers of A take responsibility for creating all the flavours of concrete A, so they are likely to have work to do when things such as kinds of B change.
In the case of
A myA = new A(myBFactory())
The client now needs to know about Bs and their factories and has complete control over which factory to use. The provider hs given the client much more responsibility, and we have perhaps increased coupling - the client code now explicitly depends on at least one more class. The provider of A has no work to do when new kinds of B come along.
Note that we are injecting the B factory and so when writing client unit tests we can now much more easily provide mocks for Bs, so testing the client tends to be easier. In general I find that I use this injection appraoch more frequently for this reason.
Compare UML diagrams at page 117 and 131. The point is, that simple Factory decides how to bake a Pizza for a PizzaStore. Factory method allows the concrete PizzaFactory to decide how to bake a Pizza. Factories are about managing dependencies. Using constructor, you have to decide which class to instantiate. Using simple factory you let concrete class to decide which class to instantiate. Using Factory method you let any class (which can) decide which class to instantiate. Using abstract Factory you let any class (which can) decide which class to instantiate regardless of what sort of instance are you wanting to create. Inversion of control is using what you got, because the decision was made when the divine existence created you.
My personal opinion is that original Design Pattern book by GoF, although being not so good in explaining, has more real world examples.
You are correct in that all that appears to change from Simple Factory to Factory Method is that in Simple Factory the factory was passed in through the constructor and we used that to create our object. In Factory Method the call is now to an abstract method in our abstract factory class; but this is powerful. Since the method is abstract it will have to be implemented in our subclasses which is what we desire. Our subclasses can implement their own variations but certain behavior is still enforced by our abstract class. What is even more powerful is that we can extend the number of factories without modifying the original code by just adding new classes that inherit from the abstract base class.
精彩评论