This isn't really an Abstract Factory. Going on the theme of what you've got above (although I'm not sure what trains, planes and buses have to do with parsing!), an Abstract Factory would look something like the following:
public interface Parser
{
List<ITransport> getBusList();
List<ITransport> getTrainList();
List<ITransport> getPlaneList();
}
public interface ParserFactory
{
Parser getParser();
}
public class XMLParser implements Parser
{
//Implementation of Constructors and Interface methods from Parser
}
public class CSVParser implements Parser
{
//Implementation of Constructors and Interface methods from Parser
}
public class XMLParserFactory implements ParserFactory
{
public Parser getParser()
{
return new XMLParser();
}
}
public class CSVParserFactory implements ParserFactory
{
public Parser getParser()
{
return new CSVParser();
}
}
This is then used in some way like the following:
public class Main
{
//Note: Using a String is for illustrative purposes only. Ideally
//it should be using some system or file setting. Half the point
//of this pattern is that the caller doesn't know what kind of
//object they are getting back (which probably doesn't make too much
//sense for parsers, really).
public static ParserFactory createParserFactory(String type)
{
if(type.equals("XML") {
return new XMLParserFactory();
} else {
return new CSVParserFactory();
}
}
public Main(ParserFactory factory)
{
Parser parser = factory.getParser();
List<ITransport> bus = parser.getBusList();
}
public static void main(String[] args)
{
new Main(createParserFactory("XML"));
}
So what's the point of all this (it's quite a lot of code, after all). Well, firstly, it insulates the caller from knowledge of the concrete type. They don't know what kind of Parser they're getting back, the implementation details are hidden from them. Secondly, it localizes all object creation through a single point, which means client code will need very minimal updates when things change. For example, say we want to add a new kind of Parser - let's say a JSONParser - to our code. Then we create a factory and parser like we did previously:
public class JSONParser implements Parser
{ // Implementation details
}
public class JSONParserFactory implements ParserFactory
{
public Parser getParser() { return new JSONParser(); }
}
Then we simply add it to our getParserFactory method:
public static ParserFactory createParserFactory(String type)
{
if(type.equals("XML") {
return new XMLParserFactory();
}
else if(type.equals("JSON") {
return new JSONParserFactory();
} else {
return new CSVParserFactory();
}
}
Note that any client code will be calling createParserFactory() and then getParser from that - so ideally, if they want to switch in a JSONParser, the only thing that needs to change in their code is the call to createParserFactory("JSON").
Hopefully this has cleared things up a little bit (and not confused you too much).