I'm working on some framework and I got an abstract class, which should be implemented.
Now I got some other stuff the user should be able to configure, but it is optional.
So instead of the abstract method:
public abstract class AbstractModule {
public void doSomething() {
if (logMessage() != null)
System.out.println(logMessage());
doStuff();
}
protected abstract String logMessage(); // I'm optional
protected abstract void doStuff();
}
I thought of just checking for an interface implementation:
public interface Log {
String logMessage();
}
public abstract class AbstractModule {
public void doSomething() {
if (this instanceof Log) {
if (((Log) this).logMessage() != null)
System.out.println(((Log) this).logMessage());
}
doStuff();
}
protected abstract void doStuff();
}
So, if someone is implementing AbstractModule with the interface Log it would also show the message. The benefit for the implementer that I see: She doesn't need to care about implementing logMessage(), as it would be in the first example. Is this a valid approach or should it be done differently?
Thanks in advance!
Best regards
I would make the Logger a component of your module and define a default no-op logger in the abstract class. This way you get rid of the instanceof
and still preserve the flexibility.
interface Log {
void logMessage();
}
public abstract class AbstractModule {
protected Log log;
public AbstractModule(){
this.log = () -> {};
}
public AbstractModule(Log log){
this.log = log;
}
public void doSomething() {
log.logMessage();
doStuff();
}
protected abstract void doStuff();
}
Here is an example class extending AbstractModule
:
public class Module extends AbstractModule{
public Module(){
super(() -> System.out.println("message"));
}
@Override
protected void doStuff() {
// do stuff
}
}
You can define a getter-method for the logger in the abstract class if you want to expose the logger:
public Log getLogger(){
return log;
}