可以在下面的代码中使用多态而不是if / else

时间:2011-07-14 18:52:41

标签: java design-patterns

我应该使用多态而不是条件,但是我可以在下面的情况下使用吗?

下面的代码根据jsonObject的内容返回一个Screen对象。

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 个答案:

答案 0 :(得分:4)

绝对。我自己一直在更多地采用多态方法,我真的很喜欢它。由于Java语言,这看起来有点臃肿。我们确实需要lambda表达式来正确执行此操作!

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的抽象类并拉出一些工作。

答案 1 :(得分:3)

在某个地方,您必须确定您的JSON对象是否代表特定类型的屏幕。因此,您必须在某处进行if次比较。就多态性而言,我对工厂方法没有太大的改进,但是你可以提供一些实用方法,它将屏幕类型作为枚举返回并用它构建switch语句。它可能看起来更好一些。但它的总体改进价值将受到限制。

答案 2 :(得分:1)

编辑:我完全改变了@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();
}