【问题标题】:Reuse code for looping through multidimensional-array重用代码以循环遍历多维数组
【发布时间】:2013-08-01 01:24:40
【问题描述】:

假设我有一个多维数组作为类的成员和许多方法,它们循环遍历数组的每个元素,然后对其进行操作。代码可能如下所示:

public class Baz {

    private Foo[][] fooArray = new Foo[100][100];

    public Baz() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Initialize fooArray
            }
        }
    }

    public void method1() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Do something with fooArray[i][j] 
            }
        }
    }

    public void method2() {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                // Do something else with fooArray[i][j] 
            }
        }
    }

    // and so on
}

现在,由于循环的代码始终相同,只有循环内的操作发生了变化,有没有什么办法可以将循环的代码重构为一个单独的方法?能做就太好了

doInLoop(functionToExecute());

如果可能的话,最接近的替代方法是什么?

【问题讨论】:

    标签: java loops refactoring command-pattern


    【解决方案1】:

    您正在寻找的是 Command 模式:定义一个单一方法接口并将其作为匿名类为每个用例实现。您将将此接口的一个实例传递给一个方法,该方法执行所有样板文件并仅为有趣的部分调用您的方法:

    public void forAllMembers(Foo[][] fooArray, Command c) {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                c.execute(fooArray[i][j]);
            }
        }
    }
    

    或者,等待 Java 8,它将引入 Lambda 并为您的问题提供一流的解决方案!

    【讨论】:

    • @Skippy 我不熟悉 python 中的驱动程序,但我很确定这个用例将被生成器及其提供的控制反转覆盖。
    • @Skippy 在除 Java 之外的所有现代语言中,lambda 函数和闭包都是主要功能。
    • @Skippy 不,C 根本没有被淘汰。发生的事情是它的范围 已经缩小到只有低级例程。但它在该领域并未面临任何反对,而且这种情况很可能会保持至少十年。
    【解决方案2】:

    你可以这样:

    public void method1(Performer p) {
        for (int i = 0; i < fooArray.length; i++) {
            for (int j = 0; j < fooArray[i].length; j++) {
                p.doIt(fooArray[i][j]);
            }
        }
    }
    
    
    static interface Performer {
    
        public void doIt(int ij);
    }
    

    然后实现不同的执行者并将它们传递给这个单一的方法。

    这种方法称为Command Pattern

    【讨论】:

      【解决方案3】:
      public Baz() {
          for (int i = 0; i < fooArray.length; i++) {
              for (int j = 0; j < fooArray[i].length; j++) {
                  fooArray[i][j] = initArray(/* .. */);
                  doSomethingWithFooArray(fooArray[i][j] );
                  doSomethingElseWithFooArray(fooArray[i][j] );
              }
          }
      }
      

      如果你想创建通用的东西,你可以使用Interface

      public interface FooItf{
         public void doSomethingWithFooArray(int value );
         public void doSomethingElseWithFooArray(int value );
         public int initArray(/* .. */);
       } 
      

      现在你可以写点什么了:

       public looping(FooItf foo) {
          for (int i = 0; i < fooArray.length; i++) {
              for (int j = 0; j < fooArray[i].length; j++) {
                  fooArray[i][j] = foo.initArray(/* .. */);
                  foo.doSomethingWithFooArray(fooArray[i][j] );
                  foo.doSomethingElseWithFooArray(fooArray[i][j] );
              }
          }
      }
      

      现在您可以基于FooItf 生成多个类并实现任何内部逻辑。

      【讨论】:

        猜你喜欢
        • 2013-04-01
        • 2012-04-21
        • 2011-01-02
        • 2014-05-01
        相关资源
        最近更新 更多