Java 在下面的代码中是否可以使用多态性代替if/else

Java 在下面的代码中是否可以使用多态性代替if/else,java,design-patterns,Java,Design Patterns,我应该在条件上使用多态性,但我可以在下面的情况下使用它吗 下面的代码根据jsonObject的内容返回一个Screen对象 public static Screen getNextScreen(){ JSONObject jsonObject = RatingsUtils.getCurrentJsonObjectFromServer(); if(isNextProgramScreen(jsonObject)) { ParentRatin

我应该在条件上使用多态性,但我可以在下面的情况下使用它吗

下面的代码根据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;
        }
}

在某些地方,您必须确定JSON对象是否代表特定类型的屏幕。因此,您必须在某个地方进行
if
比较。在多态性方面,我看不到工厂方法有多少改进,但您可以提供一些实用方法,将屏幕类型返回为enum,并使用它生成
switch
语句。它看起来可能稍微好一点。但它的整体改善价值将是有限的。

绝对。我自己也经常采用多态方法,我真的很喜欢它。因为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);
                }
            }
    );
}
私有静态列表screenProviders=screenProviders();
公共静态屏幕getNextScreen(JSONObject JSONObject){
对于(屏幕提供程序屏幕提供程序:屏幕提供程序){
if(screenProvider.supports(jsonObject)){
返回screenProvider.getScreen(jsonObject);
}
}
返回null;
}
界面屏幕提供程序{
布尔支持(JSONObject JSONObject);
Screen-getScreen(JSONObject-JSONObject);
}
私有静态列表提供程序(){
返回数组.asList(
新屏幕提供者(){
公共布尔支持(JSONObject JSONObject){
返回isNextProgramScreen(jsonObject);
}
公共屏幕getScreen(JSONObject JSONObject){
ParentRatingsObject ParentRatingsObject=JsonBusinessObjectFactory.createParentRatingsObject(jsonObject);
返回新的下一个程序屏幕(父对象);
}
},
新屏幕提供者(){
公共布尔支持(JSONObject JSONObject){
返回屏幕(jsonObject);
}
公共屏幕getScreen(JSONObject JSONObject){
ChildWithParentingSobject ChildWithParentingSobject=JsonBusinessObjectFactory.CreateChildWithParentingSobject(jsonObject);
返回新的TimerScreen(ChildWithParentingsObject);
}
},
新屏幕提供者(){
公共布尔支持(JSONObject JSONObject){
返回ISNEXTCONTENTPREJUDGESCREEN(jsonObject);
}
公共屏幕getScreen(JSONObject JSONObject){
ChildWithParentingSobject ChildWithParentingSobject=JsonBusinessObjectFactory.CreateChildWithParentingSobject(jsonObject);
返回新的NEXTCONTENTPREJECTGINGSCREEN(具有父子关系的子对象);
}
},
新屏幕提供者(){
公共布尔支持(JSONObject JSONObject){
返回isnextContentJudgeScreen(jsonObject);
}
公共屏幕getScreen(JSONObject JSONObject){
ChildWithParentingSobject ChildWithParentingSobject=JsonBusinessObjectFactory.CreateChildWithParentingSobject(jsonObject);
返回新的TimerScreen(ChildWithParentingsObject);
}
}
);
}

这种方法的一个巨大好处是getNextScreen()方法的简单性。经过一些思考,可能会使screenProviders()方法更加紧凑——也许可以添加一个抽象类来实现ScreenProvider并提取一些工作。

编辑:我完全改变了@Mike Deck建议的答案

使用枚举和多态性:

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();
}

我认为这取决于
是什么…Screen()
函数的功能。我同意@Matt。我们需要知道如何检查is…Screen()函数中的返回对象。is…Screen()函数检查jsonObject中的值属性,因此如果该属性等于预定义的字符串值,则返回true。@user470184在这种情况下,您可以去掉所有的
is…()
方法,方法是创建类型枚举并使用
HashMap
。然后可以使用一个
getJSonObjectType()
方法在映射中查找枚举值。您可以用一个switch-case构造替换if…else链。它将受到限制,直到您在其他地方需要依赖类型的分支。然后它突然变成了一个好主意,特别是如果你接着添加另一个类型…等等。组织良好的代码的大多数优点仅在运动中可见。@biziclop+1表示运动中可见的
。不过,这在很大程度上取决于该代码的未来。很难预测未来…@马特:我得请你为这句话辩护。:…创建具有多个表单的变量、函数或对象的能力…属于不同类型的对象响应相同名称的方法、字段或属性调用的能力,每个调用都符合相应的类型特定行为ScreenProvider的实现展示了典型的多态性,这绝对不是OP可能追求的简单多态性。另一方面,这其实并不重要,因为这是一个非常简洁的解决方案。您可以在枚举本身中创建一个抽象方法,然后每个枚举实例可以以不同的方式实现它。