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

Java 用设计模式替换多个If\Else,java,if-statement,design-patterns,conditional,Java,If Statement,Design Patterns,Conditional,基于SO(例如)上的各种线程,我知道我可以用命令模式替换多个if\else语句 我的情况有点不同 我有一系列命令,只有在前一个命令失败时,我才需要执行每个命令 例如,假设我需要从一个假设的网页中检索文本-我可以使用屏幕抓取直接从网页中抓取文本,或者我可以从API中获取文本。如果屏幕抓取不成功,我只想从API中获取文本。换句话说,如果“scrape”命令不起作用,我只会执行“fetch”命令 在本例中,我将测试刮取的字符串是否为空或等于null,然后执行第二个命令。如果第二个命令也不成功,我将执行

基于SO(例如)上的各种线程,我知道我可以用
命令
模式替换多个if\else语句

我的情况有点不同

我有一系列
命令
,只有在前一个命令失败时,我才需要执行每个
命令

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

在本例中,我将测试刮取的字符串是否为空或等于null,然后执行第二个命令。如果第二个命令也不成功,我将执行第三个命令,依此类推

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

我无法通过通常建议的路线(使用
映射
命令
界面)实现这一点,因为如果第一个命令失败,这将不会执行下一个
命令
(它也无法检查
命令
是否成功)


什么样的设计模式可以用来解决这个问题?

正如其他人所说,使用这种模式可以连续尝试不同的实现,直到成功

假设您的命令有这样一个接口,在该接口中,已处理的请求在成功时返回一个
结果
对象,在失败时返回
null
(也可以使用布尔值或
可选值
或任何您想要的值)

然后,您的链接命令可以包装其他几个命令,并尝试每一个命令,直到出现问题

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;
    }
}
公共类ChainedCommand实现命令{
//也可以改为在构造函数中设置
List commandChain=Arrays.asList(新的报废命令(),
新apicomand());
公共结果句柄(请求){
结果=空;
迭代器iter=commandChain.Iterator();
while(result==null&&iter.hasNext()){
结果=iter.next().handle(请求);
}
返回结果;
}
}

人们建议使用
责任链模式
然而,当我想到发生在我身上的问题时,我可以使用
命令模式的变体来解决这个问题。它是这样工作的

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

然后我们将创建一个包含所有相关命令的新类。让我们调用这个类
GetTextCommandCenter
。该类将包含
公共列表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
类添加更多类来轻松添加更多命令,或者快速更改单个命令的优先级


我认为这是解决我问题的简单而直接的方法(但如果您认为
责任链模式更合适,以及您为什么这么认为,请发表评论)

如果条件是命令固有的:运行命令,使其返回
true
,以获得成功。将所有命令放在一个列表中,运行该列表中的所有命令,直到第一个命令成功。不幸的是,Java流没有
takeWhile()
public String replaceIfElseWithCommand()..

String text = null;
int commandIndex = 0;

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

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

return text;

}