I’ll be giving a “mini-talk” on the Factory Method pattern at Atlanta PHP this evening.
Who doesn’t love the Factory Method pattern, right? Good stuff. A link to a PDF of the slides is below. I struggled to come up with a cool example, but an one related to cars was the best that I could do. You’ll find some PHP-specific example code in the slides, too.
For further reading on the Factory Method pattern and other classic design patterns, you can always grab a copy of Design Patterns: Elements of Reusable Object-Oriented Software. Enjoy!
Nice slides! But one point confuses me:
“Your factory: It’s always a static method”.
Isn’t it even better for it to be an object with methods rather than static access? This way you could switch it far more easy for testing, since you cannot mock static functions.
The Dynamic factory could be mocked to return a mock object when used for testing.
Hi,
Is there any reason you don’t use the class_exists method in your factory instead of the case statement? Performance?
http://ca3.php.net/manual/en/function.class-exists.php
Thanks
@beberlei Sure, I suppose you could make them non-static methods. Personally, I’ve never seen it done that way, and in my experience, I’ve never seen that approach documented in one of the “classic” books floating around.
But sure, I suppose you could take that approach.
In general, if a method is not dependent on a data member in an object, then that’s a sign that it might be able to be static. Hence, why factory methods are generally static.
@Saad Tazi: I assume you’re referring to the example with “foo,” “bar,” “hockey,” and “baseball” classes. That example is a pretty simple one, but you’re right, I suppose you could use a class_exists() call there.
But, on the flip side, in my later examples, I’m mapping the concept of “fast car” to Car_Ferrari, and “slow car” to Car_Yugo, so that doesn’t map as nicely.
But sure, if you had a simple string-to-class name mapping, you could use class_exists() with it.
I’m not sure that I’d recommend that for the reasons that then your developer would be able to effectively instantiate an object of ANY type from that factory, which misses the point. The idea is that any object returned should adhere to a common interface.
If you had classes “car” and “hot air balloon,” those aren’t going to have the same interface, so you wouldn’t want to be able to create both of those objects from the same factory.