Replacing if/else logic with state/strategy pattern

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.

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); 
}  

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'.

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


Following is the proper way to compile this code. The key point here is that AbstractMap.SimpleImmutableEntry is a single entry. If you wish to add more entries then you need to instantiate the class for each entry.

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