使用设计模式替换多个If / Else

4
根据 SO 上的各种线程(例如 Replacing if else statement with pattern),我了解到可以使用 Command 模式替换多个 if\else 语句。
我的情况有点不同。我有一系列的 Commands,只有在前一个命令失败时才需要执行每个 Command
例如,假设我需要从一个虚构网页中检索文本 - 我可以直接从页面中抓取文本,也可以从 API 中获取文本。只有在屏幕抓取不成功时,我才想从 API 获取文本。换句话说,如果“scrape”命令不起作用,我才会执行“fetch”命令。
在这种情况下,我将测试抓取的字符串是否为空或等于 null,然后执行第二个命令。如果第二个命令也不成功,则执行第三个命令以此类推。
重要的是,我们只有在某个条件为真/假时才执行后续命令。每个命令的条件始终相同,但将来可能会增加命令的数量。
我无法通过通常建议的路线(使用 MapCommand 接口)来实现此目的,因为这样不会执行下一个 Command 如果第一个失败(它还无法检查 Command 是否成功)。
有哪种设计模式可用于解决此问题?

1
如果条件是命令固有的:运行该命令,使其返回成功的true。将所有命令放入一个列表中,运行该列表中的所有命令直到第一个成功为止。不幸的是,Java Stream没有 takeWhile() 方法。 - dhke
5
我认为你正在寻找“责任链模式”(chain of responsibility pattern)。请参考以下链接:https://zh.wikipedia.org/wiki/%E8%B2%AC%E4%BB%BB%E9%93%BE%E6%A8%A1%E5%BC%8F - fps
2个回答

1

正如其他人所说,使用责任链模式,可以依次尝试不同的实现,直到成功为止。

假设您的命令具有此接口,在处理请求后,如果成功,则返回Result对象,如果失败,则返回null(也可以使用布尔值或Optional或任何您想要的类型)。

public interface Command{

  Result handle( Request request);
}

然后,您的链接命令可以包含多个其他命令,并尝试每个命令,直到找到可用的。
public class ChainedCommand implements Command {
    //could also be set in a constructor instead
    List<Command> commandChain = Arrays.asList( new ScrapperCommand(),
                                            new ApiCommand());


    public Result handle( Request request){

         Result result = null;
         Iterator<Command> iter = commandChain.iterator();
         while( result ==null && iter.hasNext()){
              result = iter.next().handle(request);
         }

         return result;
    }
}

-1

人们建议使用责任链模式,但是当我思考这个问题时,我想到可以使用变种的命令模式来解决这个问题。它的工作原理如下。

用实现Command接口的相应类替换每个if语句。在我们的例子中,我将实现ScreenScrapeTextCommandFetchTextFromAPICommand类。由于每个类都将实现Command接口,因此我们将向每个类添加execute()方法(此方法将实际执行我们需要的功能,例如屏幕抓取或从API获取)。

然后,我们将创建一个包含所有相关命令的新类。让我们称这个类为GetTextCommandCenter。该类将包含以以下方式的public List<Command> commandList;形式的Commands列表。然后,我们通过将前两个类添加到列表中来硬编码命令:

commandList.add(new ScreenScrapeTextCommand();
commandList.add(new FetchTextFromAPICommand();

我们可以用以下代码替换if\else链:

public String replaceIfElseWithCommand()..

String text = null;
int commandIndex = 0;

while (text == null && text == someCondition)
{

text = new GetTextCommandCenter().commandList(commandIndex).execute();
commandIndex++;
}

return text;

}

一旦命令成功,while循环中的条件将失败,方法将相应地返回。
通过向CommandCenter类添加更多类或快速更改单个命令的优先级,我们可以轻松添加更多命令。
我认为这是解决问题的简单直接的方法(但如果您认为责任链模式更合适,请放置评论,并说明您的原因)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接