0

I have this switch statement which is executed after the user is shown a list of actions to take and clicks one of them. What we switch on is the action ID

switch (actionId) {
    case 0:
        openEditProductScreen();
        break;
     case 1:
         startDeleteProductOperation();
         break;
     case 2:
          //nothing
          break;
      case 3: 
          openAddProductScreen();
          break;
}

I have read some articles on replacing switches with polymorphism but they relate to another type of problem - doing the same thing in different ways (the way you pay different types of employees), but what do I do when I want to trigger a completely different set of actions?

Thinking about it, do I really need to eliminate THIS particular kind of switch statement? I mean, it's readable and logical. What would the benefits be if I eliminated it somehow?

EDIT:

Is this what you meant?

private Map<Integer, ProductRelatedAction> productRelatedActions = new HashMap<Integer, ProductRelatedAction>();

private void mapActionsToIds() {
    productRelatedActions.put(0, new EditProductAction());
    productRelatedActions.put(1, new DeleteProductAction());
    // remainder omitted
}

private abstract class ProductRelatedAction{
    abstract void execute();
}

private class EditProductAction extends ProductRelatedAction{
    @Override
    void execute() {
        openEditProductScreen();
    }
}

private class DeleteProductAction extends ProductRelatedAction{
    @Override
    void execute() {
        startDeleteProductOperation();
    }
}
JNYRanger
  • 6,829
  • 12
  • 53
  • 81
Kaloyan Roussev
  • 14,515
  • 21
  • 98
  • 180

1 Answers1

5

Add an abstract method execute() in the Action class, create 4 subclasses of Action, overriding execute(). Make the first one execute openEditProductScreen(), the second one execute startDeleteProductOperation(), etc.

Then create one instance of these 4 classes and make the user choose one of those 4 instances. When the user has chosen the action, call selectedAction.execute().

Should you replace this kind of switch by polymorphism? In my opinion: yes. When you'll have to add another action, there is no way you'll be able to forget to implement the execute() method in the new subclass: your code won't compile without it. On the other hand, Forgetting to add a case in your switch statement is extremaly easy to do. And I'm not even mentioning the fall-through problem of switch statements.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • This sounds good. But I just edited my question, asking is it worth it? Doesnt it do more harm than good, especially to the readability of the code? – Kaloyan Roussev May 10 '15 at 15:05
  • I added a section about that in my answer. – JB Nizet May 10 '15 at 15:07
  • Thanks for the edit. So should I put those Actions in a map with and then get(actionId) from that map, as pointed out here: http://stackoverflow.com/a/126475/2576903 – Kaloyan Roussev May 10 '15 at 15:08
  • I don't know much about Android, but I guess you could simply display a selectable list of Action instances to the user, rather than displaying a list of integers, and then find the corresponding Action thanks to the map. – JB Nizet May 10 '15 at 15:10
  • Thank you. I've edited my question with an example of what I think is what you told me to do. Could you take a look? – Kaloyan Roussev May 10 '15 at 15:16
  • Yes, except that, as I told you before, I *think* you should be able to avoid the map. – JB Nizet May 10 '15 at 15:18
  • One last thing: why inherit from abstract class rather than implement an interface in this particular case? – Kaloyan Roussev May 10 '15 at 15:19
  • You should indeed probably use an interface. Or both, if some common stuff needs to be done for every action. I suggested an abstract class because I thought you already had an Action class, having an action ID. – JB Nizet May 10 '15 at 15:22
  • Oh, I see. Thank you once again – Kaloyan Roussev May 10 '15 at 15:23