Reputation: 4198
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
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
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
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
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