как избежать "каскадных if \ case" -статий в фабричном классе - PullRequest
1 голос
/ 26 октября 2019

Я должен создать объект на основе конкретной ситуации. Я читал, что решением может быть Factory Pattern, но в моем случае у него много недостатков.

Например: у меня есть приложение, которое управляет животными. В какой-то момент клиент дает мне список животных, которые должны быть созданы. Решение с использованием заводского шаблона должно быть:

//PRODUCTS
public interface  Animal {
    String getCall();
}

public class Dog implements Animal {
    public String getCall() {
        return "Bau";
    }
}

public class Cat implements Animal {
    public String getCall() {
        return "Miao";
    }
}
public class Cow {...}
public class Rooster{...}

public enum AnimalEnum {
    Cat, Dog, Cow, Rooster
}



//FACTORY
public class AnimalFactory {
    public Animal getAnimal (AnimalEnum type){
        Animal retval = null;
        switch (type){
            case Cat:
                retval = new Cat();
                break;
            case Dog:
                retval = new Dog();
                break;
            case Cow:[...]
            case Rooster[...]

        }
        return retval;
    }
}

На мой взгляд, это запах кода. Проблема в том, что я должен написать кейс-заявление, чтобы проверить, какое животное хочет клиент. Кроме того, если в будущем я хочу создать новый объект «Тигр», мне придется изменить все фабричные классы.

Мой вопрос: есть ли способ избежать этой ситуации? Есть ли шаблон, который позволяет мне создавать объект на основе другого параметра, не имея «каскадный, если \ case-of», как это?

Я думал, использовать шаблон команды, но в конце я все ещеесть такая ситуация.

1 Ответ

3 голосов
/ 26 октября 2019

Понятие «запах кода» и его противоположность, «чистый код», восходит к Мартину Фаулеру и Роберту Мартину, см. В этом посте нюансы обонятельных, гигиенических и моральных сравнений в области разработки программного обеспечения.

Что касается вопроса, то ваше мнение о том, что этот тип переключения между перечислениями воняет, согласуется с Мартином Фаулером в оригинальной редакции " Рефакторинг: улучшениеДизайн существующего кода", но он отозвал его в 2015 издание . Нет единого мнения по этому поводу, в том числе среди нескольких авторов репутации в 100K, например, @ tim-biegeleisen заявляет, что вони нет, @ mark-seemann настаивает на том, что есть , также после 2015 года, и обязательно так долгопоскольку вселенная существует, в соответствии с его склонностью.

Что касается претензии, которую вы испытываете к этому конкретному куску кода, вы можете перенести создание экземпляра в сам Enum, избегая, таким образом, оператора switch и также забываядобавить дополнительные ветви переключателей, когда вы увеличиваете перечисление.

public enum AnimalEnum {
    Cat(Cat::new), 
    Dog(Dog::new), 
    Cow(Cow::new), 
    Rooster(Rooster::new);

    private final Supplier<Animal> createAnimal;

    public Animal createInstance() {
        return createAnimal.get();
    }

    AnimalEnum(Supplier<Animal> factory) {
        this.createAnimal = factory;
    }
}

Предполагая, что это предложение вызовет противоречия, основанные на расположении отдельных обонятельных органов и сосредоточенные вокруг вонючей / чистой дихотомии, которую я хотел бы сослаться на этот пост , посвященный исключительновопрос, могут ли функции членов перечислений раздражать наши носы оправданным образом или нет.

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