1

In my application I fetch files from the user and process it.

Im to limit to a certain scope of file types and each one of these has a different processing approach.

How can I design the application in order that when a new type of file is added, I have to change few to no lines in the controller classes.

Should I be using an Adapter? Wouldn't that be just delegating change responsabilities to another class?

Should I make a representative class for files and deal with them that way?

If possible, provide a (generic) implementation example. It might help to know that Im designing a Spring MVC application and loading files with multipart files. Also, Im checking file type through extension name in the loading file controller [this might have to change].

  • 1
    What you want is to have a generic interface with a method providing abstraction (could be anything, maybe even process) and havr concrete implementations of this interface for each file type. You will then have a factory method returning you a concrete instance of said generic interface based on the type of the file you are trying to open. – Andy Oct 20 '16 at 10:48
  • Generic interface is in. On the rest let me see if I understood: I create a factory that takes the input and produce an object of the correct type? – Tiago Duque Oct 20 '16 at 11:25
2

Decorators would fit, one implementation for each of the types, one more as a facade (or dispatcher ? not sure about the term here) routing to the proper implementation.

The facade and the multiple decorator should implements the same interface, here is an example :

public interface FileProces{
    public void process(File file);
    public boolean canProcess(File file);
}

Each decorator should handle his own type of file :

public class JpgFileProces implements FileProces{
    public void process(File file){
        if(!canProcess(file)){
            throw new IllegalArgumentException();
        }
        ...
    }

    public boolean canProcess(File f){
        return f.getContentType.equals("image/jpeg");
    }
}

Then the Facade :

public FacadeFileProces{
    public Set<FileProcess> setProcess;
    public void process(File file){
         for(FileProcess process : setProcess){ 
               if(process.canProcess(file)){
                     process.process(file);
                     break;// you can either do that of for more security, either ensure that you have only one processor and not multiple that are registered.
               }
         }
    }

    public boolean canProcess(File file){
       for(FileProcess process : setProcess){
           if(process.canProcess(file)){
               return true;
           }
       }
       return false;
    }
}

Note : DavidPacker in his comment talked about factory : his solution is more usefull is your FileProcessor are not stateless. If they're not, using a factory returning only singletons is the same that I did, I'm just masking the fact that I have sublayers.

  • But then I'll still have to "swich/else if" somewhere to get the correct classes... No? That's where I'm finding trouble, for it will demand some length of maintenance. – Tiago Duque Oct 20 '16 at 11:39
  • @TiagoSirious the "if" is in the for loop in the sample i gave. There is only one if in the for loop. The only thing i didn't show you here is how to register you JpgFileProcess in the FacadeFileProcess because i don't know if you use tools like dependency injection (which help a lot), otherwise you can just make JpgFileProcess's constructor take the FacaceFileProcess as a parameter and let him self registering in). – Walfrat Oct 20 '16 at 11:43
  • So I made a FIle factory that does this: String type = file.getContentType().toString().toLowerCase(); IProcessableFile processableFile; switch (type) { case "text/plain": processableFile = new FileTxt(file.getName()); default: processableFile = null; } – Tiago Duque Oct 20 '16 at 12:53
  • @TiagoSirious you can do it like this, I just did it differently, mine is a bit more flexible, but that flexibility may not be necessary to you. I edited it a bit so you can see the whole picture. – Walfrat Oct 20 '16 at 13:53
  • Ok, now I see it! I was missing the canProcess part! – Tiago Duque Oct 20 '16 at 17:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.