3

I've been writing a website in PHP. As the code becomes more complex, I keep finding problems that can be solved using the factory design pattern. For example: I've a got a class Page which has subclasses HTMLPage, XMLPage, etc. Depending on some input I need to return an object of either one of these classes. I use the factory design pattern to do this.

But as I encounter this problem in more classes, I keep having to change code which still initiates an object using its constructor. So now I'm wondering: is it a good idea to change all code so that it uses the factory design pattern? Or are there big drawbacks?

I'm currently in a position to change this, so your answers would be really helpful.

Frog
  • 324
  • 5
  • 10
  • 3
    Use the pattern where you need to. Using it adds complexity, so you should only use it where it is required (in short, no, not for _every_ class). – Oded Nov 25 '12 at 13:35
  • 1
    But if I use it for every class my code is more consistent. Furthermore, it would also mean I wouldn't have to rewrite code when I found out I need to use a factory after all. So you think that is not as important as added complexity? – Frog Nov 25 '12 at 13:37
  • [YAGNI](http://en.wikipedia.org/wiki/You_ain't_gonna_need_it) - though consistency is important, keeping things simple is more important for making a code base understandable and readable. You don't add stuff "just in case". – Oded Nov 25 '12 at 13:40
  • Even when you otherwise might have to rewrite loads of code because you use `new Object();` everywhere? – Frog Nov 25 '12 at 13:45
  • The key word there is **might**. You **might not** as well. – Oded Nov 25 '12 at 13:47
  • In Java, which I know is not directly relevant (hence a comment, not an answer) the better IDEs can perform this refactoring (Introduce Factory method) automatically when required. Hence it is trivially easy to introduce this extra complexity for those few occasions when it is required. – Bill Michell Nov 25 '12 at 13:52
  • 1
    @Oded: Maybe you're right. I just feels inconsistent... – Frog Nov 25 '12 at 13:52
  • @BillMichell: That would be really handy! Do you happen to know something like that for PHP? – Frog Nov 25 '12 at 13:53
  • `new Thin()` creates a strong coupling. That's other reason to keep in in a single class, the Factory class. – Tulains Córdova Nov 25 '12 at 14:19
  • 1
    @user1598390: I understand that. But do you advise me never to use the new operator and use the factory pattern for every class? – Frog Nov 25 '12 at 14:23
  • Use it where it makes sense to do so, and where you're gaining something from doing it. Don't use it just because you feel some special love for a particular pattern! – Donal Fellows Nov 25 '12 at 15:49
  • @Frog: Sadly no – Bill Michell Nov 25 '12 at 16:22
  • @Oded, "Consistency" can be a strong argument actually... (especially since the overhead of implementing factory is relatively low) – Pacerier Jun 17 '14 at 13:42

4 Answers4

11

Of course not.

The factory pattern is useful if you need to encapsulate create-time polymorphism from consumers, that is, you want to provide a transparent point from which new instances of a polymorphic type are created.

If the type in question is not polymorphic, the factory pattern is pointless.

If a single point of creation doesn't make sense, neither does the factory pattern.

If it is undesirable to hide the polymorphism details away, the factory pattern is probably inappropriate, too.

As with anything that adds complexity, you should default to not using it, but spot the point at which it is beneficial early on and apply it before it is too late.

Also, consider this: If you use a factory for everything, who creates the factory? Another factory? And who creates that?

tdammers
  • 52,406
  • 14
  • 106
  • 154
  • You just specify the MainFactory and the platform runtime's factory creates your MainFactory, so that it can create the Main class. Simple as that (joking ofc). Otherwise, solid answer. – K.Steff Nov 25 '12 at 17:41
  • 1
    @tdammers, I generally agree with what I understand you're trying to transmit, which is obvious to you, but may not be for the op. "Single point of creation": what's wrong with several points of creation? "Who creates the factory": it may be a static class, a singleton that depends on configuration, etc. The problem (complexity) with factory factories is beyond the point, I guess, since the op seems to be willing to have a global factory. – acelent Nov 26 '12 at 22:53
  • @PauloMadeira: Nothing is wrong with multiple points of creation in most cases, which is exactly my point. And "who creates the factory" is kind of a rhetorical question, hinting at the fact that, given that your factories are objects, running *all* object creation through factories is logically impossible. – tdammers Nov 27 '12 at 09:13
  • @tdammers, Creating objects using a "factory" can be done with a mere static method (the **static** method **is** the "factory", there's no need to have "factory objects" so your point is invalid. – Pacerier Jun 17 '14 at 13:15
3

I don't know a lot of people using design patterns in PHP, but Joshua Bloch recommends the Factory pattern in his book, "Effective Java." In fact, it is his first recommendation: Item 1. Here are several of his points which are specific to Java, but most probably apply to PHP:

Advantages

  • As you mentioned, a factory method can return any sub-type of object
  • Unlike constructors, factory methods are not required to create a new object each time they are invoked - this allows you to manage the set of objects internally. For example, a printable ASCII character class only ever needs 95 instances. You don't need two objects to represent a lower-case 'k'.
  • Factory methods can be given meaningful names (in Java)

Disadvantages

  • In Java, you cannot create a subclass if the parent class lacks a public or protected constructor.
  • Static factory methods are not readily distinguishable from other static methods. Bloch suggests a naming pattern to distinguish them.

The goal behind most of Bloch's suggestions is that if you send your class out into the world and many people use it, you want it to present an interface that allows you to adapt and change the implementation of your classes without breaking client code. Bloch's perspective was formed by trying to fix bugs and design flaws in the Java API's without changing the interface that they present to the world.

GlenPeterson
  • 14,890
  • 6
  • 47
  • 75
3

Your question is not answerable.

"Factory" is simply too vague to be called a pattern.

If you read in GoF Design Pattern book, there is no such thing as "Factory" pattern.

Instead, there are several kinds of factory, which are Factory Method, and Abstract Factory. Different kind of factory is solving different problem. You should know what what problem you are trying to solve, before you decide you want to adopt a pattern.

So, tell us, what problem you want to solve?

Adrian Shum
  • 1,095
  • 7
  • 11
  • 1
    The Factory pattern does exist, if you look at Domain Driven Design for example - http://guptavikas.wordpress.com/2009/12/21/domain-driven-design-creating-domain-objects/ +1 for mentioning that there are multiple flavors of factories though. – guillaume31 Nov 26 '12 at 11:31
  • 1
    I was aware there are multiple types of factories, but I use a different factory type depending on my needs. For example, I've got a `Request` class on which I can call `Request::factory` (so a factory method). But I think I can specify my original question a bit more: wouldn't it be handy to create a Factory Method for every class to use instead of a constructor? Since one can do this using a single base class, it wouldn't make the code more complex. What do you think about that? – Frog Nov 26 '12 at 12:58
2

Create an static Factory class.

That class will have static methods like this:

public static class Factory{

    public static Vehicle getCarInstance(){ ... }
    public static Vehicle getPlaneInstance(){ ... }
    public static Vehicle getVehicleInstance(int TYPE){ ... }

    public static Vehicle getVehicleWithPlaqueNumber(String plaqueNo){...}

    public static Account getAccountByID(int ID){..}

}

You don't need a Factory for every class.

Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
  • 2
    Is your static Factory class a better idea than static factory methods in each class? So do you prefer `Factory::getCar()` over `Car::factory()`. If so, why? – Frog Nov 25 '12 at 16:19
  • 1
    Now you've got a class that depends on all your other classes. Not only that, but in order to properly instantiate any of those classes (Car, Plane, Account, etc.) you need to use Factory, so all your other classes depend on Factory. This is suboptimal. – Caleb Nov 25 '12 at 16:27
  • 1
    @Caleb That's the idea. The only class that is strongly coupled is the Factory class. All other classes refer to abstractions. – Tulains Córdova Nov 25 '12 at 16:34
  • 1
    @Frog That way all classes can be programmed to abstractions. The only class that deals with concrete classes is the Factory. – Tulains Córdova Nov 25 '12 at 16:42
  • 2
    @user1598390: But is that really a better than idea than having a static factory method? Why so? What's the advantage over having one very tightly coupled class? To me that sounds not good at all... – Frog Nov 25 '12 at 17:28
  • 1
    @Frog It's better to have just one tightly coupled class than many. http://www.oodesign.com/factory-pattern.html – Tulains Córdova Nov 25 '12 at 17:52
  • 2
    @Frog, TL;DR: if you have a static factory method in each class, what's the difference from using its constructor? The objective of a factory method is to decouple the actual implementation. The method should only expose the implemented interface, so a class with lots of static factory methods is tightly coupled to the interfaces, but it could use e.g. configuration, class loading and reflection for each factory to be completely decoupled from the actual classes. – acelent Nov 26 '12 at 22:35
  • @PauloMadeira: There is no difference, but using a factory method instead of a constructor would mean that you could easily change that factory method to do extra things. Like returning an object of a derived class or like passing an argument to the constructor. Isn't that a big advantage? – Frog Nov 27 '12 at 17:06
  • 1
    @Frog The issue is that with a factory method, any class that uses another class will be coupled to an implementation. **You will have a mesh network of dependencies**. With an static factory, in the other hand, classes will be only coupled to the factory class implementation. **You will have a star network of dependencies** with the static factory as the central hub. – Tulains Córdova Nov 27 '12 at 20:33
  • Mmm, thanks for all your help! I'll think about it... – Frog Nov 27 '12 at 20:40