-4

I need to execute a different action doAction1(), doAction2() ... depending on the value and/or type of some variables and return value of some functions. All combinations could be possible, in principle.

The quick solution is to test all combinations within nested if-else statements but the resulting code is quite ugly and difficult to maintain and extend (in case for instance I have new conditions to test for). I include some sample code below. I am using Java SE 8:

public static boolean myFunct () {
    return true;  // hardcoded, it could also return false
}

public static void main(String[] args) {

    int x = 1;  // hardcoded, it could also be =2
    Object o = new String();  // hardcoded, it could also be an Integer

    // here I begin to test to decide which action to execute
    if (x == 1) {
        if (o instanceof String) {
            if ( myFunct() ) {
                // do this if x==1 AND o is a String AND myFunct() returns true
                doAction1();  
            }
            else {
                doAction2();
            }
        }
        else if (o instanceof Integer) {
            if ( myFunct() ) {
                doAction3();
            }
            else {
                doAction4();
            }
        }
    }
    else if (x == 2) {
        if (o instanceof String) {
            if ( myFunct() ) {
                doAction5();
            }
            else {
                doAction6();
            }
        }
        else if (o instanceof Integer) {
            if ( myFunct() ) {
                doAction7();
            }
            else {
                doAction8();
            }
        }
    }
}

private static void doAction8() {
    // do some work...
}

private static void doAction7() {
    // do some work...
}

private static void doAction6() {
    // do some work...
}

private static void doAction5() {
    // do some work...
}

private static void doAction4() {
    // do some work...
}

private static void doAction3() {
    // do some work...
}

private static void doAction2() {
    // do some work...
}

private static void doAction1() {
    // do some work...
}

I read about a RuleEngine design pattern that could elegantly apply to this kind of cases and replace the nested if-else statements but cannot really find how to implement it for my case.

Thank you in advance for your recommendations.

ditranet
  • 51
  • 1
  • 5
  • 1
    Somewhere in future, this might be of your interest. [Pattern Matching for instanceof](https://openjdk.java.net/jeps/305) – Naman Sep 25 '19 at 10:35
  • 1
    Why do you use `o instanceof X` if `o` is not used afterwards? – Andrew Tobilko Sep 25 '19 at 10:36
  • What's the purpose of the code anyway? We know what you're trying to do, but...why? – Kayaman Sep 25 '19 at 10:40
  • @AndrewTobilko I wanted to make my code as concise as possible to focus on my actual question. My point here is that the class type of o is one of the conditions to decide which action to execute. Indeed o would be used somewhere else in reality. – ditranet Sep 25 '19 at 10:40
  • 3
    @ditranet There is a difference between making the code generic for the sake of an example and removing every bit of context from what you are trying to do. If I told you "*do the thing and then thing the other thing*" then I have made my request generic, but I have also made my request so devoid of context as to be meaningless. – Michael Sep 25 '19 at 10:44
  • The answer to your question depends on what problem you're trying to solve. The instanceof conditions suggest polymorphism might be one way to solve the issue, but that depends of whether the types of the object o, really are all some common "thing" and you can't really tell that from the very generic code example. – matt freake Sep 25 '19 at 13:59

1 Answers1

2

When you have multiple conditions and you need to perform a separate action for each combination of those conditions, one approach is as follows.

  • First, calculate a key (index) based on condition evaluations.

For example,

|---------------|---------------|---------------|---------------|
|   condition1  |   condition2  |   condition3  |      key      |
|---------------|---------------|---------------|---------------|
|     true      |     true      |     true      |      111      |
|...............|...............|...............|...............|
|     true      |     true      |     false     |      110      |
|...............|...............|...............|...............|
|     true      |     false     |     false     |      100      |
|...............|...............|...............|...............|
|     true      |     false     |     true      |      101      |
|...............|...............|...............|...............|
|     false     |     true      |     true      |      011      |
|...............|...............|...............|...............|
|     false     |     true      |     false     |      010      |
|...............|...............|...............|...............|
|     false     |     false     |     false     |      000      |
|...............|...............|...............|...............|
|     false     |     false     |     true      |      001      |
|---------------|---------------|---------------|---------------|

If a String key is used for your case,

String methodIndex = "";
methodIndex += (x == 1) ? "1" : "0";
methodIndex += (o instanceof String) ? "1" : "0";
methodIndex += (myFunct()) ? "1" : "0";

Probably bit-wise operations can be used to do this more effectively if only true-false conditions are there. Else if you have multi-value conditions (e.g. x can be 1, 2, 3...), calculating a String key will be easier.

  • Then based on the calculated key, invoke the correct action (probably using a switch statement.
switch (methodIndex) {
    case "111":
        doAction1();
        break;
    case "110":
        doAction2();
        break;
    case "101":
        doAction3();
        break;
    case "100":
        doAction4();
        break;
    case "011":
        doAction5();
        break;
    case "010":
        doAction6();
        break;
    case "001":
        doAction7();
        break;
    case "000":
        doAction8();
        break;
    default:
        System.out.println("No action defined");
}
Udith Gunaratna
  • 2,091
  • 1
  • 13
  • 17