Avoiding endless switch-case structures with classes
February 2, 2009 – 9:30 pm Tags: Design Patterns, PHPImagine the following: you have some form elements that need to render themselves. You have saved them in a database, as your users must be able to modify the forms. You have a bunch of different kinds of elements: a text field, a longer textarea field, maybe a field used for entering dates.
How would you determine, which kind of a field your code needs to render? The simple choice would be to put them in a switch block, which looks at the type of the element, and maybe calls some method based on that.
But what if you need to add a new element type? What if you need to add 10 new element types? The switch will get very long and that’s not good for readability of the code. But with some smart use of classes and polymorphism, we can easily solve this problem
A simple approach
Instead of using the switch block to decide what we want to render, we can instead load classes dynamically to do the job.
We first define an interface for them. Our example is going to be the form element, but you can use this approach with anything else too. So we will define a FormElement interface, which contains methods setData and render – setData will be used to tell the implementing class the parameters it needs to work with, such as the field’s value, and the render method will, surprisingly, be used to get the actual html code for the element.
//Let's assume $data contains things like the form element's type etc. $className = 'Form' . ucfirst($data['type']); $element = new $className; $element->setData($data); $html = $element->render();
Much nicer than a long, long switch block! And now, if we want to add a new element type, we won’t even need to modify this code as long as we stick to our naming scheme. If we used a switch, we would need to add a new case for each new element we add.
Adding to the example: using a factory
We could improve the example slightly. We can do this by introducing a factory class, which returns instances of the form element.
The advantage of this is that if you ever need to modify your naming scheme or how the element class is constructed, you will not have to touch the code that’s using them. This is even better in cases where you have more than one place where you need to create a form element: even though our code to create the new class is pretty short, it would mean we have the logic duplicated.
One additional advantage of using a factory is that sometimes you may want to have more than one “group” of items. These groups may have different ways they are created, so having a factory do this would make it easier to use.
The factory would be relatively simple: it needs a method which will return an instance of a specific kind of an element.
class FormElementFactory { public function createElement($type) { $className = 'Form' . ucfirst($type); $element = new $className; return $element; } }
Conclusion
Using a switch structure to choose between different ways of proceeding is often a simple and quick to implement way to solve the problem. However, when you start to need more than just a handful of cases, the code can often end up being difficult to read and manage.
Using classes as illustrated in the post, it’s quite simple to achieve the same result. This does add a small step of complexity into the application, and some more files to include, but it’s often worth it.
By using a factory class to create the different types of classes you can enhance the result some more, but if your use case is simple it may be worth considering if a factory is necessary – it may not be useful in every case.
ps: I used some more model diagrams in this than I usually do. Let me know if you find them helpful =)

8 Responses to “Avoiding endless switch-case structures with classes”
Hello,
This is the first time I read an article on your site. I really enjoyed it. I recocnize the problem your’e dealing with from my own experience.
What you shouldn’t forget is that eiterh you ad a whole new class ore you add a one line to a switch statement. Just depends to what you prefere.
Thanks again.
By Sanders on Feb 3, 2009
Hi Jani,
I enjoy every single one of your design pattern articles. I like the practical approach you take, and the class diagrams help too.
Can you recommend any UML editor for PHP?
Keep ‘em coming, I check your blog twice a week, and it’s definitely my favorite!
By Tix'z on Feb 3, 2009
That’s nice to hear =)
I’ve been using Microsoft Visio for the diagrams on this blog. You could also try Dia, which is free and much lighter than Visio (and should work on non-Windows OS’s too)
Oh, and if you use an rss reader you can always subscribe to the feed so you won’t need to check the site manually. My RSS feed contains the full posts (and a direct link for posting comments!) for your convenience =)
By Jani Hartikainen on Feb 3, 2009
I dosen’t use a RSS Reader because it slows my productivity down :p
If I had a RSS Reader installed I would just be checking/updating it all the time instead of getting my projects done.
By Tix'z on Feb 3, 2009
Tix’z,
Just make it a habit to check your rss feeds only in the morning before you start working. And then, close it down to the next morning.
That’s wat I do
By sanders on Feb 3, 2009
I can’t control my habits.
If I need to think something through, I used to read my rss feed, but then I lost track of what I were working on and just kept on reading feeds.
So personally I’m better of not having any RSS feeds and just check manually.
By Tix'z on Feb 3, 2009
I am amazed…
I really wish I could see an real example of this pattern at work, because I am so noob at php. I really wish I can someday understand the way to substitute switchs with classes. Could you write an example with perhaps the BEFORE and AFTER effects….
By Pio on Jun 23, 2009