如果唯一的区别是 for 循环中的方法调用,请避免重复代码

Avoid duplicated code if the only diffence is a method call in a for loop

我把这两个方法写在java:

public void fillRect(float x, float y, float width, float height, Color color) {
        int xi = mapX(x);
        int yi = mapY(y);

        int heightf =  mapHeight(height);
        int widthf  = mapWidth(width);


        if (xi + widthf > pixelWidth){
            widthf -= xi + widthf - pixelWidth;
        }
        if (yi + heightf > pixelHeight){
            heightf -= yi + heightf - pixelHeight;
        }


        if (xi < 0) {
            widthf += xi;
            xi = 0;

        }
        if (yi < 0) {
            heightf += yi;
            yi = 0;
        }

        for (int xx = xi; xx < xi + widthf; xx++){
            for (int yy = yi; yy < yi + heightf; yy++){
                // here is the difference between the other method
                setPixel(xx,yy,color);

            }
        }
    }
public void fillRect(float x, float y, float width, float height,float transparency, Color color) {
        int xi = mapX(x);
        int yi = mapY(y);

        int heightf =  mapHeight(height);
        int widthf  = mapWidth(width);

        if (xi + widthf > pixelWidth){
            widthf -= xi + widthf - pixelWidth;
        }
        if (yi + heightf > pixelHeight){
            heightf -= yi + heightf - pixelHeight;
        }


        if (xi < 0) {
            widthf += xi;
            xi = 0;

        }
        if (yi < 0) {
            heightf += yi;
            yi = 0;
        }

        for (int xx = xi; xx < xi + widthf; xx++){
            for (int yy = yi; yy < yi + heightf; yy++) {
                // here is the difference between the other method
                // this Method is slower then setPixel() 
                plot(xx,yy,transparency,color);
            }
        }
    }

我习惯于编写这样的方法 validateBoundary(float* x,float* y, float* width, float *height): void 其中包括 'if-statments' 并改为调用它,但显然是这样Java 不会发生。 解决此类问题的方法是什么?我们可以编写一个 Methode validateBoundaryWidthf(xi, widhtf, pixelWitdth) ,其中 return 是 widthf 的新值。但是像这样:

if (xi < 0) {
     widthf += xi;
     xi = 0;
}

无法解决,因为只有一个 return 值。当然,我可以创建一个具有属性 widthf 和 xi 的 POJO 和 return this,但我认为这在 cpu / 内存方面是昂贵的。那么解决这个重复代码问题的正确方法是什么?

您可以使用消费者来处理 for 循环内的不同处理。定义一个新的功能接口,它将 xxyy 值作为参数:

@FunctionalInterface
public interface PointConsumer {
    void accept(int x, int y);
}

然后添加一个新方法 performOnPoints,其中包含所有需要的参数和一个 PointConsumer 参数。它可能看起来像这样:

public void performOnPoints(float x, float y, float width,
                            float height, PointConsumer consumer) {
    int xi = mapX(x);
    int yi = mapY(y);

    int heightf =  mapHeight(height);
    int widthf  = mapWidth(width);


    if (xi + widthf > pixelWidth){
        widthf -= xi + widthf - pixelWidth;
    }
    if (yi + heightf > pixelHeight){
        heightf -= yi + heightf - pixelHeight;
    }


    if (xi < 0) {
        widthf += xi;
        xi = 0;

    }
    if (yi < 0) {
        heightf += yi;
        yi = 0;
    }

    for (int xx = xi; xx < xi + widthf; xx++){
        for (int yy = yi; yy < yi + heightf; yy++){
            consumer.accept(xx, yy);
        }
    }
}

然后您可以像这样重写现有的 fillRect 方法:

public void fillRect(float x, float y, float width, float height, Color color) {
    performOnPoints(x, y, width, height, (xx, yy) -> setPixel(xx, yy, color));
}

public void fillRect(float x, float y, float width, float height,
        float transparency, Color color) {
    performOnPoints(x, y, width, height, (xx, yy) -> plot(xx,yy,transparency,color);
}

如您所见,它们都对所有特殊 if() 语句使用相同的循环代码,但您只有一次此代码。对于不同的参数,您将使用不同的消费者对象,一个调用 setPixel(),另一个调用 plot().

您可以定义 public void fillRect(bool plot, float x, float y, float width, float height,float transparency, Color color),其中 plot 指示应使用哪个实现。当 false 时使用第一个选项。当 true 时使用第二个选项。