如何避免在Java中重复编写代码?

6

我只是一个编程新手。 uf是一个并查集类,它具有连接两个节点根的union方法。 这段代码负责打开网格的一个站点,并将该站点与其邻居(如果有)联合。如果其中一个邻居已经满了,则填充与该站点相连的所有节点。 以下是实际代码:

        if(i == 1){
            uf.union(len*len, xyTo1D(i,j));
            if(existAndOpen(i+1,j)){
                uf2.union(xyTo1D(i+1,j), xyTo1D(i,j));
                uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
            }
            if(existAndOpen(i-1,j)){
                uf2.union(xyTo1D(i-1,j), xyTo1D(i,j));
                uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
            }
            if(existAndOpen(i,j-1)){
                uf2.union(xyTo1D(i,j-1), xyTo1D(i,j));
                uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
            }
            if(!(j == len && i == len)){
                if(existAndOpen(i,j+1)){
                    uf2.union(xyTo1D(i,j+1), xyTo1D(i,j));
                    uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
                }
            }
        }
        else{
        if(existAndFull(i+1,j)){
            uf2.union(xyTo1D(i+1,j), xyTo1D(i,j));
            uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
        }
        if(existAndFull(i-1,j)){
            uf2.union(xyTo1D(i-1,j), xyTo1D(i,j));
            uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
        }
        if(existAndFull(i,j-1)){
            uf2.union(xyTo1D(i,j-1), xyTo1D(i,j));
            uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
        }
        if(!(j== len && i == len)){
            if(existAndFull(i,j+1)){
                uf2.union(xyTo1D(i,j+1), xyTo1D(i,j));
                uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
            }
        }
        if(existAndOpen(i+1,j)){
            uf.union(xyTo1D(i,j), xyTo1D(i+1,j));
        }
        if(existAndOpen(i-1,j)){
            uf.union(xyTo1D(i,j), xyTo1D(i-1,j));
        }
        if(existAndOpen(i,j-1)){
            uf.union(xyTo1D(i,j), xyTo1D(i,j-1));
        }
        if(!(j== len && i == len)){
            if(existAndOpen(i,j+1)){
                uf.union(xyTo1D(i,j), xyTo1D(i,j+1));
            }
        }
    }
    }

我该如何简化代码?


为什么不先分享你的想法呢?看起来你只是在倾倒你的作业。 - nolexa
请提供足够的代码以便我们理解您的问题。目前看来,您根本不需要那个第一个if-else语句。请访问[ask]页面并[edit]您的问题。 - z7r1k3
1
@Spencer4134:我不介意更多细节,但是这个 if 语句指定了是否在测试中使用 f1 还是 f2 - Amadan
你想要实现什么目标? - Perdomoff
@Amadan 哦,我明白了。漏掉了那部分。 - z7r1k3
1
搜索“策略模式”即可找到你想要的内容。另一个选择是访问者模式。 - DwB
4个回答

7

试试这个

boolean f1(int a, int b) { }
boolean f2(int a, int b) { }
void A(int a, int b) { }

void testAndA(BiPredicate<Integer, Integer> p, int a, int b) {
    if (p.test(a, b))
        A(a, b);
}

并且

    if(x == 1){
        testAndA(this::f1, x + 1, y);
        testAndA(this::f1, x, y + 1);
    } else {
        testAndA(this::f2, x + 1, y);
        testAndA(this::f2, x, y + 1);
    }

还可以让testAllAndA同时执行testAndA,因为它们在每个分支中都是相同的。 - Amadan

1
你可以写一个循环来遍历所有可能传递给f1()的不同值,例如以下代码:
for (int deltax = -1; deltax <= 1; deltax++) {
    for (int deltay = -1; deltay <= 1; deltay++) {
        if (f1(x + deltax, y + deltay)) {
            A(x + deltax, y + deltay);
        }
    }
}

当然,根据需要检查的条件更改deltax和deltay的起始和结束值。

1
你说每个块中有“更多的if语句”。我猜这意味着你需要使用不同的x和y偏移量调用f1/f2和A。以下是一个程序,展示了一种重构代码以避免重复编码的方法。其主要特点是:
  • It uses object orientation to abstract the inner if blocks.
  • It uses an offsets array to represent the x/y offsets for each inner if block.
  • The doIt() method uses a loop to invoke the inner if blocks.

    public class Main {
    
        static interface F {
          void f(int i, int j);
        }
    
        static class F1Caller implements F {
          public void f(int a, int b) {
            if (f1(a, b)) {
              A(a, b);
            }
          }
        }
    
        static class F2Caller implements F {
          public void f(int a, int b) {
            if (f2(a, b)) {
              A(a, b);
            }
          }
        }
    
        static boolean f1(int a, int b) { System.out.print("  f1. "); return true; }
        static boolean f2(int a, int b) { System.out.print("  f2. "); return true; }
        static void A(int a, int b) { System.out.println("a: " + a + ", b: " + b); }
    
        static F1Caller f1Caller = new F1Caller();
        static F2Caller f2Caller = new F2Caller();
    
        // x and y offsets for each call to f1/f2.
        // Add more offset rows, as needed.
        static int offsets[][] = {
            {1,  0},
            {0, -1}
        };
    
        static void doIt(int x, int y) {
          System.out.println("x: " + x + ", y: " + y);
    
          F f = (x == 1) ? f1Caller : f2Caller;
          for (int k = 0; k < offsets.length; k++) {
              f.f(x + offsets[k][0], y + offsets[k][1]);
          }
        }
    
    
        public static void main(String[] args) {
            doIt(0, 0);
            doIt(1, 0);
        }
    }
    
上述程序的输出为:


x: 0, y: 0
  f2. a: 1, b: 0
  f2. a: 0, b: -1
x: 1, y: 0
  f1. a: 2, b: 0
  f1. a: 1, b: -1

1
你可以将函数组合在一起。
使用开关。
public static boolean func(int a, int b, int fun)
{
     boolean output = false;
     switch(fun)
     {
     case 1:
         //do stuff
         output = true;
         break;
     case 2:
         //do stuff
         output = true;
         break;
     default:
         //unknown function handling
        output = false;
     }
     return output;
}

将其与for循环集成:
public static void main(String[] args)
{
     int i;
     //Change this to whatever you want or set it to a argument.
     int repeat = 2;
     for(i = 1; i <= repeat; i++)
     {
          func(a, b, i);
     }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接