我正在研究一些框架,我得到了一个抽象类,应该实现它。
现在我得到了一些用户应该能够配置的其他内容,但它是可选的。
所以不是抽象方法:
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();
}
我想过只检查接口实现:
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();
}
因此,如果有人使用接口Log实现AbstractModule,它也会显示消息。我看到的实现者的好处是:她不需要关心实现logMessage(),就像在第一个例子中那样。这是一种有效的方法还是应该以不同的方式完成?
提前致谢!
祝你好运
答案 0 :(得分:5)
我会将Logger作为模块的一个组件,并在抽象类中定义一个默认的no-op logger。这样你就可以摆脱instanceof
并保持灵活性。
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();
}
这是一个扩展AbstractModule
的示例类:
public class Module extends AbstractModule{
public Module(){
super(() -> System.out.println("message"));
}
@Override
protected void doStuff() {
// do stuff
}
}
如果要公开记录器,可以在抽象类中为记录器定义一个getter方法:
public Log getLogger(){
return log;
}
答案 1 :(得分:5)
由于此问题已标记为java-8
,因此备用解决方案是使用interface
和default
方法:
public interface Module {
public default void doSomething() {
if (logMessage() != null)
System.out.println(logMessage());
doStuff();
}
public default String logMessage() { return null; } // I'm optional
public void doStuff();
}
用法:
class NoLogModule implements Module {
@Override
public void doStuff() { }
}
class LogModule implements Module {
@Override
public void doStuff() { }
@Override
public String logMessage() { return "Message "; }
}
使用此方法而不是 Abstract 类的一个优点是您的类现在可以从另一个类扩展。这种方法的一个缺点是,你无法阻止某人覆盖 doSomething
方法(基于你的代码,它看起来你不关心这个)
答案 2 :(得分:2)
到达KeyDown
有点代码味道;这通常是一种更好的方式。
我的第一直觉是在基类中使用no-op方法:
instanceof
显然什么也没做;但是你可以在子类中重写:
class AbstractModule {
final void doSomething() {
maybeLogMessage();
}
void maybeLogMessage() {}
}
会打印信息。
如果您不想在所有子类中重复class Subclass extends AbstractModule {
@Override void maybeLogMessage() {
System.out.println("The message");
}
}
,则可以从方法返回一个特殊值,以表明它不应该被记录。例如,您可以要求字符串为非空:
System.out.println