2

I am designing an application that makes use of asynchronous HTTP downloads. I want this application to work on Android, Windows desktops and Mac OS desktops, which is why I am developing it in Java and try to make it very modular.

enter image description here

(edit for clarity, the libraries Im using are AsyncHttpClient and Android-Async-Http)

I already have libraries to handle the downloads, but the problem is that specific methods in the CORE module have to be able to perform download functionality irregardless of what library is used. I had two ideas on what to do.

  • Idea 1: Put an abstract class called GenericDownloader in CORE and extend it in specific apps with classes like AndroidDownloader.
  • Idea 2: Put an interface called DownloadInterface in CORE, implement it in specific apps in a similar way to idea 1.

The problem with both of these ideas is that I cannot instantiate an abstract class or an interface, so how can I implement the functionality in CORE?

How else can I solve this problem?

Dreen
  • 6,976
  • 11
  • 47
  • 69
  • why can't you instantiate the abstract class? http://stackoverflow.com/questions/4587392/can-we-create-a-instance-of-java-interface – Narendra Pathai Dec 04 '12 at 15:20
  • @artbristol: can you elaborate? – Dreen Dec 04 '12 at 15:24
  • 1
    @Dreen I can't put it better than Martin Fowler http://martinfowler.com/articles/injection.html. – artbristol Dec 04 '12 at 15:35
  • @NarendraPathai He can't because it's impossible. You cannot instantiate abstract classes or interfaces without providing the implementation for all abstract methods. That's why it's called abstract. – atamanroman Dec 04 '12 at 16:06

2 Answers2

0

Attempt

Have a concrete class that does the actual downloading (in CORE). This is NOT the GenericDownloader abstract class.

Your GenericDownloader class would contain this concrete downloader as a protected member. Your GenericDownloader class will then be an event listener for whatever the concrete downloader needs for it to listen to (Complete, IOError, etc.). You will need to create those listener functions. Make them protected because your children will need to override them.

Now, in your children classes, you override those "virtual" event listener functions from GenericDownloader, remembering inside them to call super.someDowloadEventHandler(...). Whatever else is in these overrides would be your platform-specific code. Remember that you can still access the concrete downloader from any child for additional manipulation.

You don't instantiate the abstract class. You only instantiate the concrete downloader in the abstract class's constructor. SO, remember to call super() in the constructor of your children classes.

You many now reference the right library from a project, then instantiate instances of AndroidDownloader if you're working in Android, WindowsDownloader for Windows, etc. Any of them will have the lower-level functionality of the CORE.

Mickael Caruso
  • 8,721
  • 11
  • 40
  • 72
0

First of all, whether to use an interface or abstract base class is a question of whether the core can and should provide functionality to implementations of the downloader. If it can't, or it shouldn't, don't use an abstract base class. Prefer an interface to an abstract base class. Even if it can, consider providing a separate class to provide the functionality which implementations can use. Prefer encapsulation over inheritance.

The answer to your specific question is, "it depends". Generally speaking you need some way to tell the core about the implementation(s) available to it at run-time.

Depending on how you package things it might be as simple as having a loader factory method in the core which looks for each implementation using Class.forName() in turn until it finds one; this assumes you package one implementation with each distributed JAR.

Otherwise, it might use a configuration entry somewhere to specify the class name of the implementation; again reflection is used to find the class.

Otherwise, you can use reflection and search the classpath looking for classes which implement your interface.

Otherwise, you can use java.net.URLClassLoader to create a class path on the fly and load classes dynamically using it.

Lawrence Dol
  • 63,018
  • 25
  • 139
  • 189