When does such "heavy use" turn into outright abuse?
What it seems like you're asking is "Am I abusing Default Methods?".
When in doubt about how to use a new piece of functionality I typically turn to the Java tutorials. As is the case with other new pieces of functionality in Java 8, there is documentation about Default Methods here.
One specific snippet that caught my eye is this:
"Default methods enable you to add new functionality to the interfaces of your libraries and ensure binary compatibility with code written for older versions of those interfaces."
I would ask yourself several questions about the implementation in assessing whether or not the new functionality is being abused:
- Am I exposing too much business logic in the interface through the default methods?
- Is there sufficient justification to expose the methods through the interface as opposed to having them implemented in an abstract class?
- Is the code going to be maintainable?
- Am I using the default methods feature in the way which it was created to be used?
To address your question about overdoing it, in my opinion you are. The documentation seems to imply what you should be using default methods for and this does not fit that mold. Especially since you're starting with an empty slate as opposed to adding new functionality to existing libraries for which you have to maintain binary compatibility.
In addition, take a look at the Java 8 List interface. Default methods are provided which accept other functional arguments and utilize those arguments on the implemented instance. The same seems true for the Comparator interface.
From the snippet provided it seems like the default methods do not utilize functional arguments. I also don't see any advantage of doing things this way over using the template pattern (which it seems like you're doing anyway) and having an abstract base class declare the
doApply method and have the abstract class call that from behind the curtain of the interface.
I'm biased in that I favor hiding functionality behind interfaces as opposed to exposing it. I perceive the intention of interfaces to be encapsulating data and hiding business logic and design following those concepts.
Here is some reading pertaining to anti-patterns that I try to keep in mind that may be applicable to your question:
Also, Oracle almost HAD to add some kind of functionality to the language that would provide backwards compatibility with existing libraries while also injecting new functionality. I consider the usage that the developers of the language chose to be a good starting place for evaluating my own usage.
As an aside, there looks to be some really cool stuff in your project.