Java structure/pattern(s) to return specific field from subclasses

163 Views Asked by At

For a project we have a requirement to create an interfacedefinition that will return all available filetype extensions that our component can export...

The problem is that we want avoid configuration/properties files. We don't want to edit our configuration/propertie file when another filetype is added (in the future). The structure of this part of our component is as follows:

public abstract class FileType {
    protected String filetype;

    public FileType(String filetype){
        this.filetype = filetype;
    }

    public abstract void export(String path, Object information);
}


public class PdfExport extends FileType {
    public PdfExport() {
        super("pdf");
    }

    public void export(String path, Object information){
        //pdf specific logic
    }
}

But how do we solve this when another component calls the interfacedefinition getExportTypes()? (How do we get a list of all available filetypes?) Taking into account the requirement to add in the future new classes that extend abstract class filetype (add new filetypes)?

Does anyone has suggestions, maybe another structure of above example? Or any (design) that discuss above issue?

Thanks in advance!

3

There are 3 best solutions below

7
GETah On BEST ANSWER

This is the exact purpose of the strategy pattern. The strategies here are the FileTypes that encapsulate an algorithm that exports a file. In the following example:

public class Application{
 List<FileType> exporters = new ArrayList<FileType>();
 public void addExporter(FileType fileExporter){
  exporters.add(fileExporter);
 }
 public void exportData(Object information){
   for(FileType exporter : exporters){
    exporter.export("d:\Export", information);
   }
 }
}

The Application class holds a list of exporters that can be filled out on the go. The Application class does not have to know what type of file exporter is registered nor how the file can be exported. When the data is exported, the Applicaiton class loops through registered exporters and delegates the export task to each one of them.

EDIT Below is an example of the Application class usage.

// Define a pdf exporter
PdfExport pdfExport = new pdfExport();
Application app = new Application();
// Register the new exporter
app.addExporter(pdfExport);
// Export some data...
app.export(information);

EDIT How to avoid configuration files and changing the code everytime you have a new FileType? You can load the exporters at runtime using reflexion (see this link for details)

0
Jeffrey On

You could do something like this:

public interface FileType {
    public String getFileType();
    public void export(String path, Object info);
}

public enum DefaultFileType implements FileType {
    PDF(".pdf"){
        public void export(String path, Object info) {
            // do pdf stuff
        }
    }, TXT(".txt"){
        public void export(String path, Object info) {
            //do txt stuff
        }
    };

    private final String fileType;

    private DefaultFileType(String fileType) {
        this.fileType = fileType;
    }

    public String getFileType() {
        return fileType;
    }

    public abstract void export(String path, Object info);
}

Then you can have a Set<FileType> in your class of all the supported FileTypes. This way anyone who wants to add a supported FileType but cannot edit your enum can still do so.

1
Vadym S. Khondar On

You can use reflection to scan classes which implement your interface.

Have a look at similar question: At runtime, find all classes in a Java application that extend a base class