fortm
fortm

Reputation: 4198

Nested IF statements

I often get in situation where I need to write such a code as below Any design pattern for doing this neatly without a flood of IF statements -

A obj = new A();
B obj2 = new B();

for ( i = 1 ; i < 20  ; i ++ )  {

if( i == 1 ) 
  obj.setField1(obj2.getOption1())
else if ( i == 2 ) 
  obj.setField1(obj2.getOption2())
else if ( i == 3 ) 
  obj.setField1(obj2.getOption3())

And so on.. for 20 times .. 

obj.setField2(obj2.getNonOptionField2());
obj.setField3(obj2.getNonOptionField3())

}

EDIT -

Analogy to looping here is that I am looping on a database and each record creates 20 more records in some other table. IN the 20 records, most columns are same except the one I added condition on.

YEah design is not the greatest, but I don't have option.

Upvotes: 2

Views: 213

Answers (4)

DJDMorrison
DJDMorrison

Reputation: 1327

Try using a switch case instead.

For example, your code would be:

for ( i = 1 ; i < 20  ; i ++ )  {
    switch(i){
        case(1): obj.setField1(obj2.getOption1());
                 break;
        case(2): obj.setField1(obj2.getOption2());
                 break;
        case(3): obj.setField1(obj2.getOption3());
                 break;
    }
}

Upvotes: 2

elgaz
elgaz

Reputation: 403

+1 to dasblinkenlight's use of interface and the pattern as suggested. A growing if/switch is often a code smell that indicates some OO refactoring is appropriate. You could add a method to pass in new MyAction instances to the map. The benefit of this approach over if and switch constructs is that:

1 - implements the Open to extension, closed to modification policy. You want to add a new behaviour? No need to add another condition to an ever-growing original class, you just create a new implementation of MyAction and pass it in.

2 - behaviour can be altered runtime by changing the content of the map.

depending on your exact requirement, you may not need a actionByNumberto be a Map, maybe a list would do, ordered or sorted if necessary.

Upvotes: 0

pamphlet
pamphlet

Reputation: 2104

One option is a switch statement.

Another option is to make obj2 keep an array of options, and access it by index. Something like:

obj.setField1(obj2.options[i]);

People will argue about the O-Oness of this, but you could dress it up in an accessor method.

Upvotes: 1

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726479

In cases when an action is conditioned upon an integer value, you can create a Map<Integer,MyAction>, where MyAction is an interface that you define for this specific purpose. Put implementations of MyAction into the map to correspond to the integer options, and call actions in run-time in response to the values coming in:

interface MyAction {
    void setField(A obj, B obj2);
}
...
Map<Integer,MyAction> actionByNumber = new HashMap<Integer,MyAction>();
actionByNumber.put(1, new MyAction() {
    void setField(A obj, B obj2) {
        obj.setField1(obj2.getOption1());
    }
});
actionByNumber.put(2, new MyAction() {
    void setField(A obj, B obj2) {
        obj.setField1(obj2.getOption2());
    }
});
...
A obj = ...
B obj2 = ...
for (int i = 0 ; i != 20 ; i++) {
    MyAction action = actionByNumber.get(i);
    if (action != null) {
       action.setField(obj, obj2);
    }
}

Upvotes: 3

Related Questions