Tuesday, February 2, 2010

SomeBean+SomeBeanImpl or just SomeBean?

Java programs consist of classes (or beans). It can be just (let’s say) ‘SomeBean’, like:

public class SomeBean {
public void someMethod1() {...}
public void someMethod2() {...}
public void someMethod3() {...}
}


However many programmers use something like this:



public interface SomeBean {
public void someMethod1();
public void someMethod2();
public void someMethod3();
}

public class SomeBeanImpl implements SomeBean {
@Override
public void someMethod1() {...}
@Override
public void someMethod2() {...}
@Override
public void someMethod3() {...}
}


The second way requires a bit more effort. What is the benefit from it? It’s possible to make many implementations of the bean. It also makes it possible to use Decorator or Proxy design patterns. For example you can enhance the functionality of ‘SomeBeanImpl’ with:



public class SomeBeanDecorator implements SomeBean {
private SomeBean decorated;

@Override
public void someMethod1() {
// some extra instructions
decorated.someMethod1();
// some extra instructions
}
...
}


The same could be achieved with inheritance, but it’s less flexible, so it’s better to use interfaces.



If ‘SomeBean’ is used only in your JAR (or WAR, or EAR, or whatever), then you know if it will be decorated or not, so you know whether an interface is needed or not. If ‘SomeBean’ is public and meant to be used by other JARs, you don’t know if those other JARs will decorate it, or not. So it’s better to make ‘SomeBean’ an interface if it’s ‘exported’.



However there are exceptions: enums (usually nobody decorates enum methods) and DTOs (their methods are also unlikely to be decorated). The same is true for listeners – never decorated.



public interface MouseListener extends EventListener {
public void mouseClicked(MouseEvent e);
public void mousePressed(MouseEvent e);
public void mouseReleased(MouseEvent e);
public void mouseEntered(MouseEvent e);
public void mouseExited(MouseEvent e);
}
...
object.addMouseListener(new MouseListener(){...} {
public void mouseClicked(MouseEvent e){...}

public void mousePressed(MouseEvent e){}

public void mouseReleased(MouseEvent e){}

public void mouseEntered(MouseEvent e){}

public void mouseExited(MouseEvent e){}
});


You have to implement all methods while you just need to catch ‘mouseClicked’. It should look like:



public class MouseListener extends EventListener {
public void mouseClicked(MouseEvent e){}
public void mousePressed(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
}
...
object.addMouseListener(new MouseListener(){...} {
public void mouseClicked(MouseEvent e){...}
});


In Java Swing it’s solved by pair ‘MouseListener’ (interface) and ‘MouseAdapter’ (class with empty implementations). In fact it’s enough to just make ‘MouseListener’ a class – no ‘MouseAdapter’ is needed.



So:




  • enums, listeners and DTOs usually don’t have to have interfaces, even if they are exported to other JARs;


  • ‘public’ not-exported and ‘package’ beans need to have interfaces only if decorated in the implementing JAR, or have more than one implementation inside it;


  • ‘public’ exported beans (and not enums, not listeners, not DTOs) should have interfaces, because they could be decorated or proxied by the client.



That’s all. What do you think about this checklist?

Share this post: