2

我经常遇到需要编写如下代码的情况任何设计模式都可以巧妙地做到这一点,而无需大量的 IF 语句 -

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())

}

编辑 -

这里循环的类比是我在数据库上循环,每条记录在其他表中创建 20 多条记录。在 20 条记录中,除了我添加条件的那一列之外,大多数列都是相同的。

是的,设计不是最好的,但我别无选择。

4

4 回答 4

3

如果操作以整数值为条件,您可以创建一个Map<Integer,MyAction>,其中MyAction是您为此特定目的定义的接口。将 的实现MyAction放入映射中以对应于整数选项,并在运行时调用操作以响应传入的值:

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);
    }
}
于 2013-03-06T15:45:58.910 回答
2

尝试改用开关盒

例如,您的代码将是:

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;
    }
}
于 2013-03-06T15:48:15.297 回答
1

一种选择是switch声明。

另一种选择是obj2保留一个选项数组,并通过索引访问它。就像是:

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

人们会争论这个的 O-Oness,但你可以用访问器方法来修饰它。

于 2013-03-06T15:47:38.263 回答
0

+1 dasblinkenlight 使用界面和建议的模式。不断增长的 if/switch 通常是一种代码异味,表明某些 OO 重构是合适的。您可以添加一个方法来将新的 MyAction 实例传递到地图。这种方法相对于ifswitch构造的好处是:

1 - 实现对扩展开放,对修改关闭的策略。你想添加一个新的行为?无需为不断增长的原始类添加另一个条件,您只需创建 MyAction 的新实现并将其传入。

2 - 行为可以通过改变地图的内容在运行时改变。

根据您的确切要求,您可能不需要 actionByNumber 成为 Map,如果需要,可能需要一个列表,排序或排序。

于 2013-03-06T17:29:01.350 回答