Replace plural If \ Else with design pattern

Based on various threads on SO (like Replacing an if else with a pattern ) I understand that I can replace multiple if \ else statements with a pattern Command

,

My situation is a little different.

I have a series Commands

, and I only need to execute each one Command

if the previous command was unsuccessful.

For example, suppose I need to get text from a hypothetical web page - I could clear the text directly from the page using screen-scrolling, or I could get text from an API. I would like to get the text from the API if the screen scraper was not successful. In other words, I would run the "fetch" command if the "scrape" command didn't work.

In this case, I would check if the cleared string is empty or zero and then execute the second command. If the second command also failed, I would execute the third command, etc.

The important point is that we only execute subsequent commands if a certain condition is true / false. The condition is always the same for each team, but the number of teams may grow in the future.

I cannot implement this with the usually suggested route (using interface Map

and Command

), because it will not lead to the next Command

one if the first one failed (it also could not check if t20> was successful or not)

What design pattern can you use to solve this problem?

+3


source to share


2 answers


As others have said, use Chain of Responsibility . A pattern that can keep executing different implementations in sequential order until it succeeds.

Suppose your command has this interface where the processed request returns an object Result

if it succeeds or null

if it doesn't work (boolean or Optional

or whatever can be used as well )

public interface Command{

  Result handle( Request request);
}

      



Then, your chained command can wrap several other commands and try each one until something works.

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

      

0


source


People suggested using a template chain of responsibility

, however, since I was thinking about the problem I was having, I could use a variation of the template Command

to solve this problem. It works like this.

Replace each operator if

with the appropriate class that implements the interface Command

. In our example, I would implement the classes ScreenScrapeTextCommand

and FetchTextFromAPICommand

. Since each class will implement the interface Command

, we will add a method execute()

to each class (this method will actually perform the functions we need, such as screen scripting or API fetching).

Then we will create a new class that contains all related commands. Let's call this class GetTextCommandCenter

. The class will contain list

of Commands

in the form public List<Command> commandList;

. We'll then be hard-coded commands by adding the first two classes to the list like this:

commandList.add(new ScreenScrapeTextCommand();
commandList.add(new FetchTextFromAPICommand();

      

We then replaced the chain if\else

like this:



public String replaceIfElseWithCommand()..

String text = null;
int commandIndex = 0;

while (text == null && text == someCondition)
{

text = new GetTextCommandCenter().commandList(commandIndex).execute();
commandIndex++;
}

return text;

}

      

Once the command is successful, the condition in the while loop will fail and the method will return accordingly.

This way we can easily add additional commands by adding more classes to a class CommandCenter

or quickly changing the priority of individual commands.

I think this is a simple and simple solution to my problem (but please post a comment if you think the template is chain of responsibility

more appropriate and why you think so)

0


source







All Articles