So, let’s start with some background [modified to make more concrete[. I have realised I can replace the following:
abstract class MessageHandler {
public void handleMessage(Message m) {
validateMessage(m);
processMessage(m);
}
protected void validateMessage(Message m) {
// Default validation logic
}
protected abstract void processMessage(Message m);
}
class FakeMessageHandler extends MessageHandler {
proteced void processMessage(Message m) {}
}
with the next block of code:
interface IMessageProcessor {
public void processMessage(Message m);
}
class FakeMessageProcessor implements IMessageProcessor {
public void processMessage(Message m) {}
}
class MessageHandler {
private IMessageProcessor processor;
public MessageHandler(IMessageProcessor processor) {
this.processor = processor;
}
public void handleMessage(Message message) {
validateMessage(message);
processor.processMessage(message);
}
protected void validateMessage(Message message) {
// Default validation logic.
}
}
That is, I can replace the abstract method with an injected interface to allow for easier testing. Now let’s say that the design stipulates that people can optionally override the methods:
class FakeMessageHandler extends MessageHandler {
protected void validateMessage(Message m) {}
protected void processMessage(Message m) {}
}
The injected interface now cannot be used as there is only 1 abstract method in MessageHandler. Yet, I can’t force the injected interface to contain method validateMessage(Message message) as the original point of using the abstract class was to define a default implementation of this method.
Is there some sort of elegant pattern to convert this into composition for the purposes of dependency injection and easier testing?
Here’s my take on this:
Instead of extending the MessageHandler, I have a single MessageHandler-class, that is a composition of IMessageProcessor and IMessageValidator:

Hope I got the UML-diagram right, it’s been a while…
Anyway, let’s take a look at the MessageHandler:
The MessageHandler has two private members, IMessageProcessor and IMessageValidator (It is a composition of a processor and a validator). Validator can be left unset, in which case the default-validation logic will kick in when handling a message.
In this example, if the passed-in processor also implements the IMessageValidator-interface,it will be used as the validator. This is probably what you wanted, because you can use the same constructor to build MessageHandlers using the default validation or custom-validation logic, depending if the passed in object implements only IMessageProcessor or both IMessageProcessor and IMessageValidator (for convenience, I have extended a third interface, IValidatingMessageProcessor from these interfaces). If the validator-logic is implemented separately (only implements IMessageValidator), it can be set using the setValidator-method.
There’s no need to extend MessageHandler, as you can implement both the processing and validation -logic outside of the handler, either separately or in a single class that implements both processing and validation.
Here are the classes I’ve used, hope this helps:
Zip-package in MediaFire
Text-form:
Message.java:
IMessageProcessor.java:
IMessageValidator.java:
IValidatingMessageProcessor.java:
FakeMessageProcessor.java:
FakeMessageValidator.java:
FakeMessageProcessorAndValidator.java:
Simple testing main for the above classes (just outputs stuff):
output: