Design Strategy of CSV Parser
First, there would be much duplication between the parser classes. This kind of duplication should be avoided. If you find a bug in the way the csv is being parsed, you now have to fix it in multiple places. Consider using the template method pattern. In this scenario, you would extract the common logic into an abstract superclass with 1 or more abstract "template methods" that would be implemented by the subclasses. For instance, the abstract superclass could parse the fields into an array or strings, then pass the array to a method to construct an object using those fields.

public abstract class AbstractCSVParser&lt;T&gt; implements CSVParser&lt;T&gt; {

    public List&lt;T&gt; parseCSVFile(String fileName) {
        List&lt;T&gt; list = new ArrayList&lt;T&gt;();

        // for each line...
        String[] fields = // parse line into an array of strings
        T obj = buildObject(fields);
        list.add(obj);

        return list;
    }

    protected abstract T buildObject(String[] fields);

}

public class csvBParser extends AbstractCSVParser&lt;ObjectB&gt; {

    protected ObjectB buildObject(String[] fields) {
        ObjectB obj = new ObjectB();
        // populate object with fields
        return obj;
    }

}




In the parsing code, the InputStream and BufferedReader are never closed. Make sure you close resources when you are done with them, and make sure it is happening inside a finally block.

BufferedReader br = new BufferedReader(new InputStreamReader(is));
try {
    // do work with br
}
finally {
    br.close();
}


If you are using Java 7, you should check out the try-with-resources statement. The above example could be written like this:

try (BufferedReader br = new BufferedReader(new InputStreamReader(is))) {
    // do work with br
} // close is called automatically at the end of the try block




In this example, the parser classes appear to be stateless. Given this, CSVParserFactory doesn't really need to return a new instance every time. One option to simplify CSVParserFactory is to initialize a static Map containing the parser instances.

public class CSVParserFactory {

    private static final Map&lt;TableType, CSVParser&gt; PARSERS = new HashMap&lt;TableType, CSVParser&gt;() {{
        put(A, new csvAParser());
        put(B, new csvBParser());
        put(C, new csvCParser());
        // etc
    }};

    public static CSVParser getParser(TableType type) {
        CSVParser parser = PARSERS.get(type);
        if (parser == null) {
            throw new IllegalArgumentException("No such table type");
        }
        return parser;
    }

}


If you don't want this, and still want to create the parser instances each time, you could use the same strategy with the class names instead of instances, then create the instance using reflection.



Finally, you may want to consider passing an InputStream to parseCSVFile instead of a file name. This would allow more flexibility of the source of the data. The current implementation is very specific as to the source.