Альтернативный способ реализации вложенного оператора if - PullRequest
0 голосов
/ 12 февраля 2019

Я пытаюсь провести рефакторинг этого кода, приведенного ниже, который использует несколько вложенных операторов if, чтобы проверить, содержат ли два списка одинаковые элементы.

List<Car> CarList = CarService.findCarByConfigtype(pageName);
for (int i = 0; i < CarList.size(); i++) {
    System.out.println(CarRestApiController.data().getModel());
    if (CarList.get(i).getModel().equals(CarRestApiController.data().getModel())) {
        dataFound.add(CarList.get(i).getModel());
        if (CarList.get(i).getDerivative().equals(CarRestApiController.data().getDerivative())) {
            dataFound.add(CarList.get(i).getDerivative());
            if (CarList.get(i).getSvp().equals(CarRestApiController.data().getSvp())) {
                dataFound.add(CarList.get(i).getSvp());
                if (CarList.get(i).getEngine().equals(CarRestApiController.data().getEngine())) {
                    dataFound.add(CarList.get(i).getEngine());
                    if (CarList.get(i).getFueltype().equals(CarRestApiController.data().getFueltype())) {
                        dataFound.add(CarList.get(i).getFueltype());
                        if (CarList.get(i).getBodystyle().equals(CarRestApiController.data().getBodystyle())) {
                            dataFound.add(CarList.get(i).getBodystyle());
                            if (CarList.get(i).getTransmission().equals(CarRestApiController.data().getTransmission())) {
                                dataFound.add(CarList.get(i).getTransmission());
                                if (CarList.get(i).getSalescategory().equals(CarRestApiController.data().getSalescategory())) {
                                    dataFound.add(CarList.get(i).getSalescategory());
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Решением может быть использование Шаблон проектирования стратегии .Иметь стратегию для каждого оператора if, выполнять итерацию по списку стратегий и обрабатывать каждую машину в списке

public interface CarFeatureStrategy {

    boolean canProcess(Car carToProcess, Car carToMatch);

    Object process(Car carToProcess);
}

Метод canHandle должен инкапсулировать операторы if, которые должны быть истинными, чтобы разрешить обработку иметод process должен возвращать значение соответствующего свойства автомобиля (для примера в описании должно быть 8 стратегий)

public class ModelStrategy implements CarFeatureStrategy {

    @Override
    public boolean canProcess(Car carToProcess, Car carToMatch) {
        return carToProcess.getModel().equals(carToMatch.getModel));
    }

    @Override
    public Object process(Car carToProcess) {
        return carToProcess.getModel();
    }
}

public class DerivativeStrategy implements CarFeatureStrategy {

    @Override
    public boolean canProcess(Car carToProcess, Car carToMatch) {
        return carToProcess.getModel().equals(carToMatch.getModel())
                && carToProcess.getDerivative().equals(carToMatch.getDerivative());
    }

    @Override
    public Object process(Car carToProcess) {
        return carToProcess.getDerivative();
    }
}

public class SvpStrategy implements CarFeatureStrategy {

    @Override
    public boolean canProcess(Car carToProcess, Car carToMatch) {
        return carToProcess.getModel().equals(carToMatch.getModel())
                && carToProcess.getDerivative().equals(carToMatch.getDerivative())
                && carToProcess.getSvp().equals(carToMatch.getSvp());
    }

    @Override
    public Object process(Car carToProcess) {
        return carToProcess.getSvp();
    }
}

// .... and so on for each condition which needs to be met
// EngineStrategy, FueltypeStrategy, BodystyleStrategy,
// TransmissionStrategy, SalescategoryStrategy

CarProcessor возвращает автомобили, соответствующие данному pageName, извлекает данные из CarRestApiController и использует список стратегий для обработки автомобилей

public class CarProcessor {


    private CarService carService;
    private CarRestApiController restController;

    private List<CarFeatureStrategy> carFeatureStrategies;

    public void processCars(Object pageName) {
        // for example purpose the list of strategies is initialized here,
        // but it should be initialized somwhere where the initialization is done
        // only once rather than each time the processCars method is called
        carFeatureStrategies = new ArrayList<>();
        carFeatureStrategies.add(new ModelStrategy());
        carFeatureStrategies.add(new DerivativeStrategy());
        carFeatureStrategies.add(new SvpStrategy());
        // ....
        // add to the strategies list an instance of each strategy to process 
        // the car

        Car carToMatch = restController.data();
        List<Car> cars = carService.findCarByConfigtype(pageName);
        List<Object> dataFound = new ArrayList<>();

        for (Car carToProcess : cars) {
            for (CarFeatureStrategy carFeatureStrategy : carFeatureStrategies) {
                if (carFeatureStrategy.canProcess(carToProcess, carToMatch)) {
                    dataFound.add(carFeatureStrategy.process(carToProcess));
                }
            }
        }
    }
}

Пример можно оптимизировать с помощью шаблона проектирования Цепочка ответственности .При цепочке ответственности операторы if в методах canHandle будут упрощены до одного булевого условия для стратегии.

Для цепочки ответственности стратегии должны быть расширены с помощью метода, который возвращает следующую стратегию вchain

public interface CarFeatureStrategy {

    boolean canProcess(Car carToProcess, Car carToMatch);

    Object process(Car carToProcess);

    CarFeatureStrategy next();
}

реализация стратегий должна быть улучшена со ссылкой на следующую стратегию в цепочке

public class ModelStrategy implements CarFeatureStrategy {

    private CarFeatureStrategy nextStrategy;

    public ModelStrategy(CarFeatureStrategy nextStrategy) {
        this.nextStrategy = nextStrategy;
    }

    @Override
    public boolean canProcess(Car carToProcess, Car carToMatch) {
        // check only the model
        return carToProcess.getModel().equals(carToMatch.getModel));
    }

    @Override
    public Object process(Car carToProcess) {
        return carToProcess.getModel();
    }

    @Override
    public CarFeatureStrategy next() {
        return this.nextStrategy;
    }
}

public class DerivativeStrategy implements CarFeatureStrategy {

    private CarFeatureStrategy nextStrategy;

    public DerivativeStrategy(CarFeatureStrategy nextStrategy) {
        this.nextStrategy = nextStrategy;
    }

    @Override
    public boolean canProcess(Car carToProcess, Car carToMatch) {
        // check only the derivative property
        return carToProcess.getDerivative().equals(carToMatch.getDerivative());
    }

    @Override
    public Object process(Car carToProcess) {
        return carToProcess.getDerivative();
    }

    @Override
    public CarFeatureStrategy next() {
        return this.nextStrategy;
    }
}

// ... and so on for all the strategies

* CarProcessor должна создать цепочку стратегий и обработать каждую машинупока цепочка не будет завершена (метод текущей стратегии next вернет ноль) или текущая стратегия не сможет обработать текущий автомобиль (метод текущей стратегии * 1030 вернет false)

public class CarProcessor {

    private CarService carService;
    private CarRestApiController restController;

    public void processCars(Object pageName) {
        // for example purpose the chain of responsibilities is initialized here,
        // but it should be initialized somwhere where the initialization is done
        // only once rather than each time the processCars method is called

        // initialise the chain of responsibilities in revers order
        CarFeatureStrategy salesCategoryStrategy = new SalescategoryStrategy(null);
        CarFeatureStrategy transmissionStrategy = new TransmissionStrategy(salesCategoryStrategy);
        CarFeatureStrategy bodystyleStrategy = new BodystyleStrategy(transmissionStrategy);
        CarFeatureStrategy fueltypeStrategy = new FueltypeStrategy(bodystyleStrategy);
        CarFeatureStrategy engineStrategy = new EngineStrategy(fueltypeStrategy);
        // .... and so on until the first strategy in the chain
        CarFeatureStrategy modelStrategy = new ModelStrategy(...);

        Car carToMatch = restController.data();
        List<Car> cars = carService.findCarByConfigtype(pageName);
        List<Object> dataFound = new ArrayList<>();

        for (Car carToProcess : cars) {
            CarFeatureStrategy currentStrategy = modelStrategy;
            do {
                if ( !currentStrategy.canProcess(carToProcess, carToMatch)) {
                    // if current strategy cannot process the current car
                    // stop the chain
                    break;
                }

                dataFound.add(currentStrategy.process(carToProcess));
                // move to the next strategy in the chain
                currentStrategy = currentStrategy.next();

            } while (currentStrategy != null)
        }
    }
}
0 голосов
/ 12 февраля 2019

Я бы сначала сохранил результат CarList.get(i) и CarRestApiController.data() в переменные, как предложил @TJCrowder.Тогда я бы перевернул if-проверки и использовал continue, чтобы избавиться от вложенности.Как это:

List<Car> carList = CarService.findCarByConfigtype(pageName);

for (int i = 0; i < carList.size(); i++) {
     Car apiData = CarRestApiController.data();
     Car carListData = carList.get(i);

     System.out.println(CarRestApiController.data().getModel());

     if (!carListData.getModel().equals(apiData.getModel())) {
         continue;
     }
     dataFound.add(carListData.getModel());

     if (!carListData.getDerivative().equals(apiData.getDerivative())) {
         continue;
     }
     dataFound.add(carListData.getDerivative());

     if (!carListData.getSvp().equals(apiData.getSvp())) {
         continue;
     }
     dataFound.add(carListData.getSvp());

     // ... and so on.
 }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...