基于SO上的各种线程(例如Replacing if else statement with pattern)我明白我可以用Command
模式替换多个if \ else语句。
我的情况有点不同。
我有一系列Commands
,只有在前一个命令不成功时才需要执行每个Command
。
例如,假设我需要从假设的网页中检索文本 - 我可以使用屏幕抓取直接从页面中抓取文本,或者我可以从API中获取文本。如果屏幕抓取不成功,我只想从API获取文本。换句话说,如果“scrape”命令不起作用,我只会执行“fetch”命令。
在这种情况下,我将测试刮取的String是否为空或等于null,然后执行第二个Command。如果第二个命令也不成功,我会执行第三个命令,依此类推。
重要的是,如果某个条件为真/假,我们只执行后续命令。每个命令的条件始终相同,但命令的数量可能在将来增加。
我无法通过通常建议的路由(使用Map
和Command
接口)实现此功能,因为如果第一个失败,这将不会执行下一个Command
(它也将是无法检查Command
是否成功)
可以使用哪种设计模式来解决这个问题?
答案 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
接口的相应类。在我们的示例中,我将实现类ScreenScrapeTextCommand
和FetchTextFromAPICommand
。由于每个类都将实现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
模式更合适并且为什么这么认为,请发表评论)