用状态/策略模式替换if / else逻辑 [英] Replacing if/else logic with state/strategy pattern

查看:596
本文介绍了用状态/策略模式替换if / else逻辑的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读过以前的堆栈交换有关用Java替换条件逻辑(例如IF / ELSE),但是我不确定我的案例是否适合替换。
这是我看到的耦合 - Java中if语句的长列表将许多'if else'语句转换为更清洁的方法

I have read the previous stack exchanges on replacing conditional logic in Java such as IF/ELSE with State/Strategy patterns but I am not sure whether my case is a proper fit for the replacement. Here are coupled I looked at - Long list of if statements in Java and Converting many 'if else' statements to a cleaner approach

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

I am essentially writing a file download manager and these are my IF/ELSE constructs:


  1. 如果文件及其zip文件存在,则将zip文件移至zip文件目录并读入文件

  2. 如果zip文件存在则解压缩文件并将zip文件移动到zip文件目录并读入文件

  3. 如果zip文件不存在,则从指定的URL
    下载然后解压缩并读入文件并移动zip文件到指定目录。

  4. 如果URL中不存在zip文件,则创建空白文件并将其写入磁盘。

  1. If the file and it's zip file exist then move zip file to zip file directory and read in file
  2. If the zip file exists then unzip file and move zip file to zip file directory and read in file
  3. If the zip file does not exist then download it from specified URL and then unzip it and read in file and move zip file to specified directory.
  4. If the zip file does not exist in URL then create blank file and write it out to disk .

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

Essentially as I understand it you put these four conditions as keys in a Hashed map and then values are the "Commands" that need to be issued. However I believe you still need an If/Else to decide what action to be invoked on the key that is given as input. So I fail to see the benefit. Can somebody explain ?

推荐答案

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

I think you should use GoF pattern Chain of responsibility. You should introduce two interfaces: 1) Condition where you will check proper condition, e.g. "If the zip file does not exist" and return boolean result - "true" if condition is satisfied, otherwise "else", 2) Execution strategy, that will run action assigned with condition, e.g. "download it from specified URL and then unzip it and read in file and move zip file to specified directory." So, 1st interface will be answer to the question "when", and 2nd - "then". "Condition" implementation and "execution strategy" implementation should be combined into "tuple" (or pair, entry, etc). This "tuple" should be moved to collection in order, that you've described. Then, when you need to handle zip file, you'll iterate over collection, invoking conditions and checking results, if result is "true" then invoking appropriate "execution strategy". Also, condition can be combined with execution strategy and moved into single interface/implementation with two methods. Context, that will describe current state of zip file can be passed between conditions/execution strategies. Hope this helps.

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

Update. Code example (in 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); 
}  

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

Remarks: 1) you can implement 'Condition' as anonymous classes, 2) 'AlwaysSatisfiedCondition' can be singleton, 3) if you're using Java/Groovy/Scala, you can use Guava/Apache Commons 'Predicate' instead of 'Condition', 'Function' or 'Closure' instead of 'Action'.

如果你需要在第一个'满意'条件和适当的行动执行后退出,那么就把'break'/'返回'行动执行后。

If you need to exit after first 'satisfied' condition and appropriate action execution then just put 'break'/'return' after action execution.

这篇关于用状态/策略模式替换if / else逻辑的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆