Избегайте дублирования кода, если единственное отличие - это вызов метода в цикле for - PullRequest
0 голосов
/ 30 мая 2020

У меня есть эти два метода, написанные на 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. Какое решение таких проблем? Мы могли бы написать Methodde validateBoundaryWidthf (xi, widhtf, pixelWitdth), который возвращает новое значение для widthf. Но что-то вроде этого:

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

не может быть решено этим, потому что есть только одно возвращаемое значение. Конечно, я мог бы создать POJO с атрибутами widthf и xi и вместо этого вернуть this, но я предполагаю, что это дорого с точки зрения процессора / памяти. Итак, как правильно решить эту проблему с дублированным кодом?

Ответы [ 2 ]

3 голосов
/ 30 мая 2020

Вы можете использовать потребителей для обработки различных операций внутри for l oop. Определите новый функциональный интерфейс, который принимает значения xx и yy в качестве аргументов:

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

0 голосов
/ 30 мая 2020

Вы можете определить public void fillRect(bool plot, float x, float y, float width, float height,float transparency, Color color), где plot указывает, какую реализацию следует использовать. Если false, используйте первый вариант. Если true, используйте второй вариант.

...