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

gan*_*sub 7 java state if-statement strategy-pattern

我已经阅读过以前的堆栈交换,用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来决定在作为输入给出的键上调用什么动作.所以我没有看到好处.有人可以解释一下吗?

nnd*_*dru 5

我认为你应该使用 GoF 模式的责任链。您应该引入两个接口:1)Condition您将在其中检查正确的条件,例如“如果 zip 文件不存在”并返回布尔结果 - 如果条件满足,则返回“true”,否则返回“else”,2)Execution strategy,这将运行指定条件的操作,例如“从指定的 URL 下载它,然后解压缩它并读入文件并将 zip 文件移动到指定的目录。” 因此,第一个界面将回答“何时”问题,第二个界面将回答“那么”问题。“条件”实现和“执行策略”实现应该组合成“元组”(或pair、entry等)。这个“元组”应该按照你描述的顺序移动到集合中。然后,当您需要处理 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<Map.Entry<Condition, Action>> steps = Arrays.asList(
 new AbstractMap.ImmutableEntry<Condition, Action>(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<Condition, Action> step: steps) {
 if(!step.getKey().isSatisfied(pathToFile))
   continue;

 step.getValue().execute(pathToFile); 
}  
Run Code Online (Sandbox Code Playgroud)

备注:1) 您可以将 'Condition' 实现为匿名类,2) 'AlwaysSatisfiedCondition' 可以是单例,3) 如果您使用的是 Java/Groovy/Scala,您可以使用 Guava/Apache Commons 'Predicate' 而不是 'Condition' ', 'Function' 或 'Closure' 而不是 'Action'。

如果您需要在第一个“满足”条件和适当的动作执行后退出,那么只需在动作执行后放置 'break'/'return'。