Blaine Lafreniere
Blaine Lafreniere

Reputation: 3600

How can I refactor this Java code so it is more DRY?

In scripted/dynamic languages it seems this would be simple and easy... however it doesn't seem to be the case in Java, or I'm just missing something.

Here's my code currently:

switch (selectedModel) {
     case "author":
        switch (selectedAction) {
            case "create":
                AuthorController.create();
                break;
            case "read":
                AuthorController.read(promptForID());
                break;
            case "update":
                AuthorController.update(promptForID());
                break;
            case "destroy":
                // AuthorController.destroy(promptForID());
                break;
        }
        break;
    case "book":
        // now I have to repeat all the same code...

I'm going to have to repeat all the same code again for the case of "book". I would think there's a better way.

Upvotes: 0

Views: 122

Answers (3)

Mikhail Dudin
Mikhail Dudin

Reputation: 1

It's possible to eliminate outer switch using some sort of a Factory pattern. And nested switch using kind of a Strategy pattern.

Rough implementation below (I hope, you are using Java 8+).

public void someServiceMethod(String selectedModel, Action selectedAction, String input) {
  ActionController controller = ActionControllerFactory.forModel(selectedModel);
  selectedAction.accept(controller, input);
}


public interface ActionController {
  void create();
  void read(String id);
  void update(String id);
  void destroy(String id);
}

public enum Action implements BiConsumer<ActionController, String> {
  CREATE {
    @Override
    public void accept(ActionController controller, String input) {
      controller.create();
    }
  },
  READ {
    @Override
    public void accept(ActionController controller, String input) {
      controller.read(input);
    }
  },
  UPDATE {
    @Override
    public void accept(ActionController controller, String input) {
      controller.update(input);
    }
  },
  DESTROY {
    @Override
    public void accept(ActionController controller, String input) {
      controller.destroy(input);
    }
  }
}

Upvotes: 0

Andreas
Andreas

Reputation: 159114

You can't do it while using static methods. Create an interface:

public interface CrudController {
    void create();
    void read(String id);
    void update(String id);
    void destroy(String id);
}

Now have all the controllers implement that interface, then your code becomes:

CrudController controller;
switch (selectedModel) {
    case "author":
        controller = new AuthorController();
        break;
    case "book":
        controller = new BookController();
        break;
    ...
    default:
        throw new IllegalArgumentException("Unknown model: " + selectedModel);
}

switch (selectedAction) {
    case "create":
        controller.create();
        break;
    case "read":
        controller.read(promptForID());
        break;
    case "update":
        controller.update(promptForID());
        break;
    case "destroy":
        // controller.destroy(promptForID());
        break;
    default:
        throw new IllegalArgumentException("Unknown action: " + selectedAction);
}

Upvotes: 4

GBlodgett
GBlodgett

Reputation: 12819

Create a common interface for all the common classes (Controller perhaps) and then do:

 Controller control;
 switch (selectedModel) {
        case "author":
            control = AuthorController; 
            break;
        case "book":
            control = BookController;
            break;
 }
 switch (selectedAction) {
      case "create":
          control.create();
          break;
      case "read": 
       //etc
 }

Upvotes: 2

Related Questions