Share

From this page you can share Java Tip of the Day: Using Interfaces to a social bookmarking site or email a link to the page.
Social WebE-mail
Enter multiple addresses on separate lines or separate them with commas.
Java Tip of the Day: Using Interfaces
(Your Name) has forwarded a page to you from Ajaxonomy
(Your Name) thought you would like to see this page from the Ajaxonomy web site.

Java Tip of the Day: Using Interfaces

Tagged:  

Anyone who has ever programmed in Java is intimately familiar with using the interface, Java's purely abstract class and cleaner answer to C++'s concept of multiple inheritance. It's an old idea by now, and yet new ideas can somehow breathe life into old ones. And this is what has happened recently with interfaces.

The obvious use of interfaces is in abstracting behavior (i.e., methods) of objects and allowing implementing classes to implement this behavior. For example, take an interface for returning an SQL connection from different sources:

public interface ConnectionFactory() { 
     public Connection getConnection(); 
}

public class JndiConnectionFactory() { 
     public Connection getConnection()  { 
          // get DataSource from JNDI, return Connection 
     }
}

public class SingleConnectionFactory() {
     public Connection getConnection()  { 
          // create Connection using properties and return
     }
}

Here the ConnectionFactory interface is defined using two different implementations, one for container environments (JNDI) and the other when used in a non-container (stand-alone) environment (JDBC).

OK, this is old news. But there is another, more subtle, use of interfaces if you think about them as a replacement for multiple inheritance or as being somewhat akin to "aspects" in AOP: that interfaces are a way of layering behavior onto an object. Thought of this way, the style of defining monolithic interfaces with many methods becomes less desirable than defining many interfaces that define one or a few methods that describe a single aspect of an object's behavior.

Let me give two examples of this idea, one from the core language itself and the other my own.

First, the core language. When Java 5 was introduced, a few simple one-method common interfaces were also introduced. One of these was the java.lang.Iterable interface which defined the simple method public Iterator iterator(). Combined with the introduction of generics, this allowed the addition of a new "foreach" construct that looks like:

for(T obj : Iterable<T>) {
     //...logic here...
}

By isolating the simple behavior of returning an iterator, Java 5 was able to have any class that implements this be used in the new "foreach" loop (not just Collections). Joshua Bloch has also proposed an addition to Java 7 of having "resource blocks" where any object that implements a Closeable interface will be automatically closed at the end of the block.

The second example has to do with defining public and private APIs. What if, in the example above, I were using the ConnectionFactory in designing a framework that would be used as a library in other Java applications, and I wanted to define an internally used Connection that I did not want exposed to the client of the library? And that I also want to use the JndiConnectionFactory and SingleConnectionFactory implementations above with this internally-used Connection?

One approach might be to create two different ConnectionFactory objects, exposing one to the client and the other hidden internally to the framework. This is a perfectly reasonable approach, but let's say (for purposes of illustration) that this is cumbersome because of the framework design and you would rather have a single, centralized ConnectionFactory that defines another method, public Connection getInternalConnection(). This presents a problem because you really don't want to expose this private API method to the client (one of Java's limitations is that there aren't a lot of options for information hiding between classes: package private or protected).

A clever solution to this issue might be to define two separate interfaces, one that exposes a public API and the other that exposes a private API. This way you can have the various implementing classes implement both the public and private API, and you only hand out a reference to the public API to the client.

public interface InternalConnectionFactory {
     public Connection getInternalConnection();
}

public class JndiConnectionFactory 
     implements ConnectionFactory, InternalConnectionFactory { ... }

public class ConnectionFactoryWrapper implements ConnectionFactory {
     private ConnectionFactory wrappedFactory;
     public ConnectionFactoryWrapper(ConnectionFactory wrappedFactory) {
          this.wrappedFactory = wrappedFactory;
     }
     //delegate methods here
}

//etc...

// This class defines the way the client gets a connection factory...
public class AppContext {
     public ConnectionFactory getConnectionFactory() { 
          return new ConnectionFactoryWrapper(connFactoryImpl);
     }
}

The wrapper class here is used to protect the internal methods from being accessed by the client (could also use a dynamic proxy here). This promotes a cleaner, simpler public API without "polluting" it with methods meant to be only used internally by the framework.

OSGi and the upcoming Java Module System handle this need in a much more robust way, but using OSGi may not be practical for most programmers and use of JSR-277 may be very far away for most organizations which are just migrating to Java 5. Clever use of interfaces addresses this need in a simple and practical way.