"Replace conditional with polymorphism" is elegant only when type of object you're doing switch/if statement for is already selected for you. As an example, I have a web application which reads a query string parameter called "action". Action can have "view", "edit", "sort", and etc. values. So how do I implement this with polymorphism? Well, I can create an abstract class called BaseAction, and derive ViewAction, EditAction, and SortAction from it. But don't I need a conditional to decided which flavor of type BaseAction to instantiate? I don't see how you can entirely replace conditionals with polymorphism. If anything, the conditionals are just getting pushed up to the top of the chain.
EDIT:
public abstract class BaseAction { public abstract void doSomething(); } public class ViewAction : BaseAction { public override void doSomething() { // perform a view action here... } } public class EditAction : BaseAction { public override void doSomething() { // perform an edit action here... } } public class SortAction : BaseAction { public override void doSomething() { // perform a sort action here... } } string action = "view"; // suppose user can pass either "view", "edit", or "sort" strings to you. BaseAction theAction = null; switch (action) { case "view": theAction = new ViewAction(); break; case "edit": theAction = new EditAction(); break; case "sort": theAction = new SortAction(); break; } theAction.doSomething(); // So I don't need conditionals here, but I still need it to decide which BaseAction type to instantiate first. There's no way to completely get rid of the conditionals.
Benefits. This technique adheres to the Tell-Don't-Ask principle: instead of asking an object about its state and then performing actions based on this, it's much easier to simply tell the object what it needs to do and let it decide for itself how to do that. Removes duplicate code.
Replacing a switch statement directly with polymorphism would work, if the conditional was based on the Type of the object, which you simply overcome by using the Type of the interface.
You're right - "the conditionals are getting pushed up to the top of the chain" - but there's no "just" about it. It's very powerful. As @thkala says, you just make the choice once; from there on out, the object knows how to go about its business. The approach you describe - BaseAction, ViewAction, and the rest - is a good way to go about it. Try it out and see how much cleaner your code becomes.
When you've got one factory method that takes a string like "View" and returns an Action, and you call that, you have isolated your conditionality. That's great. And you can't properly appreciate the power 'til you've tried it - so give it a shot!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With