Можно ли использовать полиморфизм вместо if / else в приведенном ниже коде - PullRequest
2 голосов
/ 14 июля 2011

Я должен использовать полиморфизм над условными обозначениями, но могу ли я использовать его в следующих случаях?

Ниже код возвращает объект Screen в зависимости от содержимого jsonObject.

public static Screen getNextScreen(){

        JSONObject jsonObject = RatingsUtils.getCurrentJsonObjectFromServer();

        if(isNextProgramScreen(jsonObject)) {
            ParentRatingsObject parentRatingsObject = JsonBusinessObjectFactory.createParentRatingsObject(jsonObject);
            return new NextProgramScreen(parentRatingsObject);
        } 
        else if(isTimerScreen(jsonObject)) {
            ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
            return new TimerScreen(childWithParentRatingsObject);
        } 
        else if(isNextContestantPreJudgeScreen(jsonObject)) {
            ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
            return new NextContestantPreJudgingScreen(childWithParentRatingsObject);
        } 
        else if(isNextContestantJudgeScreen(jsonObject)) {
            ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
            return new TimerScreen(childWithParentRatingsObject);
        } 
        else {
            return null;
        }
}

Ответы [ 3 ]

4 голосов
/ 14 июля 2011

Абсолютно. Я сам чаще использую полиморфный подход, и он мне действительно нравится. Из-за языка Java это будет выглядеть несколько раздутым. Нам действительно нужны лямбда-выражения, чтобы сделать это правильно!

private static List<ScreenProvider> screenProviders = screenProviders();

public static Screen getNextScreen(JSONObject jsonObject) {
    for (ScreenProvider screenProvider : screenProviders) {
        if (screenProvider.supports(jsonObject)) {
            return screenProvider.getScreen(jsonObject);
        }
    }
    return null;
}

interface ScreenProvider {
    boolean supports(JSONObject jsonObject);
    Screen getScreen(JSONObject jsonObject);
}

private static List<ScreenProvider> screenProviders() {
    return Arrays.asList(
            new ScreenProvider() {
                public boolean supports(JSONObject jsonObject) {
                    return isNextProgramScreen(jsonObject);
                }

                public Screen getScreen(JSONObject jsonObject) {
                    ParentRatingsObject parentRatingsObject = JsonBusinessObjectFactory.createParentRatingsObject(jsonObject);
                    return new NextProgramScreen(parentRatingsObject);
                }
            },
            new ScreenProvider() {
                public boolean supports(JSONObject jsonObject) {
                    return isTimerScreen(jsonObject);
                }

                public Screen getScreen(JSONObject jsonObject) {
                    ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
                    return new TimerScreen(childWithParentRatingsObject);
                }
            },
            new ScreenProvider() {
                public boolean supports(JSONObject jsonObject) {
                    return isNextContestantPreJudgeScreen(jsonObject);
                }

                public Screen getScreen(JSONObject jsonObject) {
                    ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
                    return new NextContestantPreJudgingScreen(childWithParentRatingsObject);
                }
            },
            new ScreenProvider() {
                public boolean supports(JSONObject jsonObject) {
                    return isNextContestantJudgeScreen(jsonObject);
                }

                public Screen getScreen(JSONObject jsonObject) {
                    ChildWithParentRatingsObject childWithParentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
                    return new TimerScreen(childWithParentRatingsObject);
                }
            }
    );
}

Огромным преимуществом этого подхода является простота вашего метода getNextScreen (). Подумав, можно сделать метод screenProviders () более компактным, возможно, добавив абстрактный класс, который реализует ScreenProvider и извлекает часть работы.

3 голосов
/ 14 июля 2011

В каком-то месте вам придется определить, представляет ли ваш объект JSON определенный тип экрана. Так что вам придется где-то делать эти if сравнения. Я не вижу особых улучшений для вашего фабричного метода с точки зрения полиморфизма, но вы можете предоставить некоторый служебный метод, который возвращает тип экрана в виде enum и строит оператор switch с ним. Это может выглядеть немного лучше. Но общая ценность улучшения будет ограничена.

1 голос
/ 14 июля 2011

РЕДАКТИРОВАТЬ : я полностью изменил свой ответ в соответствии с предложением @Mike Deck.

Использование Enum и полиморфизм:

public Enum ScreenType {
   NEXT_PROGRAM() {
     @Override public ScreenType generateScreen() {
        ParentRatingsObject parentRatingsObject = JsonBusinessObjectFactory.createChildWithParentRatingsObject(jsonObject);
        return new NextProgramScreen(parentRatingsObject);
     }
   },
   TIMER() {@Override...},
   NEXT_CONSTESTANT_PREJUDGE() {@Override...},
   NEXT_CONSTESTANT_JUDGE() {@Override...};

   public static ScreenType getScreenType(JSONObject jsonObject) {
      // basically rewrite your methods isXXXXXXX(jsonObject) here
   }

   public abstract Screen generateScreen();
}

И в оригинальном методе ничего не остается сделать:

public Screen generateScreen() {
   JSONObject jsonObject = RatingsUtils.getCurrentJsonObjectFromServer();     
   ScreenType screenType = ScreenType.getScreenType(jsonObject));
   return screenType.generateScreen();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...