用状态/策略模式替换if / else逻辑

我已经阅读过以前的堆栈交换,用Java替换条件逻辑,例如带有状态/策略模式的IF / ELSE,但我不确定我的案例是否适合替换。 以下是我看到的结果 – Java中的if语句的长列表以及将许多’if else’语句转换为更干净的方法

我本质上是在编写一个文件下载管理器,这些是我的IF / ELSE结构:

  1. 如果文件及其zip文件存在,则将zip文件移动到zip文件目录并读入文件
  2. 如果zip文件存在,则解压缩文件并将zip文件移动到zip文件目录并读入文件
  3. 如果zip文件不存在,则从指定的URL下载,然后解压缩并读入文件并将zip文件移动到指定的目录。
  4. 如果URL中不存在zip文件,则创建空白文件并将其写入磁盘。

基本上我理解你将这四个条件作为哈希映射中的键,然后值是需要发出的“命令”。 但是我相信你仍然需要一个If / Else来决定在作为输入给出的键上调用什么动作。 所以我没有看到好处。 有人可以解释一下吗?

我认为你应该使用GoF模式责任链 。 您应该引入两个接口:1)您将检查正确条件的条件,例如“如果zip文件不存在”并返回布尔结果 – 如果条件满足则返回“true”,否则返回“else”,2) Execution strategy ,即将运行分配了条件的操作,例如“从指定的URL下载它然后解压缩并读入文件并将zip文件移动到指定的目录”。 因此,第一个界面将回答“何时”,第二个 – “然后”。 “条件”实现和“执行策略”实现应该组合成“元组”(或对,条目等)。 这个“元组”应该按照你所描述的顺序移动到集合中。 然后,当您需要处理zip文件时,您将迭代收集,调用条件和检查结果,如果结果为“true”,则调用适当的“执行策略”。 此外,条件可以与执行策略结合,并通过两种方法转移到单个接口/实现中。 上下文,将描述zip文件的当前状态,可以在条件/执行策略之间传递。 希望这可以帮助。

更新。 代码示例(在Java中)。

 /** * All implementations should check proper condition */ interface Condition { /** * Check if condition is satisfied * * @param pathToFile path to target file * @return 'true' if condition is satisfied, otherwise 'false' */ boolean isSatisfied(String pathToFile); //i've made an assumption that you'll manipulate file path for checking file } ... /** * Childs will wrap some portion of code (if you'll use language, that supports lambdas/functors, this interface/implementation can be replaced with lambda/functor) */ interface Action { /** * Execute some portion of code * * @param pathToFile path to target file */ void execute(String pathToFile); } ... class ZipFileExistsCondition implements Condition { @Override public boolean isSatisfied(String pathToFile) { ... //check if zip file exists } } ... class ZipFileDoesNotExists implements Condition { @Override public boolean isSatisfied(String pathToFile) { ... //download zip file and move it to some temp directory //if file downloaded ok, than return 'true' otherwise 'false' } } ... class AlwaysSatisfiedCondition implements Condition { @Override public boolean isSatisfied(String pathToFile) { ... //always returns 'true', to run action assigned with this condition } } ... Collection> steps = Arrays.asList( new AbstractMap.ImmutableEntry(new ZipFileExistsCondition(), new Action() { /*move zip file to zip file directory and read in file*/ }), new ZipFileDoesNotExists(), new Action() { /*download it from specified URL and then unzip it and read in file and move zip file to specified directory*/ }, new AlwaysSatisfiedCondition(), new Action() { /*create blank file and write it out to disk*/ } ); ... String pathToFile = ... ... for(Map.Entry step: steps) { if(!step.getKey().isSatisfied(pathToFile)) continue; step.getValue().execute(pathToFile); } 

备注:1)您可以将’Condition’实现为匿名类,2)’AlwaysSatisfiedCondition’可以是单例,3)如果你使用的是Java / Groovy / Scala,你可以使用Guava / Apache Commons’Predicate’而不是’Condition ‘,’function’或’关闭’而不是’动作’。

如果你需要在第一个’满意’条件和适当的动作执行后退出,那么只需在执行动作后放入’break’/’return’。

以下是编译此代码的正确方法。 这里的关键点是AbstractMap.SimpleImmutableEntry是一个单独的条目。 如果您希望添加更多条目,则需要为每个条目实例化该类。

 Collection> steps = Arrays.asList ( (new AbstractMap.SimpleImmutableEntry (new FileExistsCondition(), new Action() { public void execute(String pathToFile){System.out.println("the path to file is srtm " + pathToFile);} } ) ), (new AbstractMap.SimpleImmutableEntry (new ZipFileExistsCondition(), new Action() { public void execute(String pathToFile){System.out.println("the path to file is " + pathToFile);} } ) ), (new AbstractMap.SimpleImmutableEntry (new ZipFileDoesNotExistCondition(), new Action() { public void execute(String pathToFile){System.out.println("the path to file is " + pathToFile);} } ) ) );