用设计模式替换多个If \ Else

时间:2017-03-29 19:26:44

标签: java if-statement design-patterns conditional

基于SO上的各种线程(例如Replacing if else statement with pattern)我明白我可以用Command模式替换多个if \ else语句。

我的情况有点不同。

我有一系列Commands,只有在前一个命令不成功时才需要执行每个Command

例如,假设我需要从假设的网页中检索文本 - 我可以使用屏幕抓取直接从页面中抓取文本,或者我可以从API中获取文本。如果屏幕抓取不成功,我只想从API获取文本。换句话说,如果“scrape”命令不起作用,我只会执行“fetch”命令。

在这种情况下,我将测试刮取的String是否为空或等于null,然后执行第二个Command。如果第二个命令也不成功,我会执行第三个命令,依此类推。

重要的是,如果某个条件为真/假,我们只执行后续命令。每个命令的条件始终相同,但命令的数量可能在将来增加。

我无法通过通常建议的路由(使用MapCommand接口)实现此功能,因为如果第一个失败,这将不会执行下一个Command(它也将是无法检查Command是否成功)

可以使用哪种设计模式来解决这个问题?

2 个答案:

答案 0 :(得分:0)

正如其他人所说,使用Chain of Responsibility模式可以继续尝试不同的实现,直到成功为止。

让我们假设您的Command具有此接口,其中处理的请求如果成功则返回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 :(得分:0)

人们建议使用chain of responsibility模式但是当我想到我遇到的问题时,我可以使用Command模式的变体来解决这个问题。它的工作原理如下。

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

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

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类添加更多类来轻松添加更多命令,或者快速更改各个命令的优先级。

我认为这是解决我的问题的一个简单而直接的解决方案(但如果您认为chain of responsibility模式更合适并且为什么这么认为,请发表评论)