// CommandBuilder.java
public class CommandBuilder {
public String name; // required
public String description = "Default Value"; //optional
public CommandBuilder(String name) {
this.name = name;
}
public CommandBuilder setDescription(String description) {
this.description = description;
return this;
}
public CommandBuilder build() {
return this;
}
}
// Command.java
public abstract class Command extends ListenerAdapter {
private String name;
private String description;
protected abstract void execCommand(MessageReceivedEvent event);
public Command(CommandBuilder builder) {
this.name = builder.name;
this.description = builder.description;
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
execCommand(event);
}
}
// ExampleCommand.java
public class ExampleCommand extends Command {
public ExampleCommand(CommandBuilder builder) {
super(builder);
}
@Override
protected void execCommand(MessageReceivedEvent event) {
// ...
}
}
// Bot.java
public class Bot() {
public static void main(String[] args) {
// ...
jdaBuilder.addEventListener(
new ExampleCommand(
new CommandBuilder("Example Command").setDescription("You know it.").build();
)
);
// ...
}
}
所以,我需要一些关于代码风格的建议。以上大致是我在JDA中为一个不和谐的机器人设置的代码。jdaBuilder.addEventListener(Object)
做什么或者MessageReceivedEvent
是什么并不重要。
在使用继承类型Command
构造对象时,我使用构建器模式来避免过多的构造函数重载,因为在我的实际代码中,Command
类可以接受的不仅仅是两个参数。CommandBuilder
的问题是,build()
不能也不能返回Command
类型的对象(因为它是抽象的),而是返回类型CommandBuilder
本身,命令的每个子类都将其作为参数(然后传递给Command
)。作为回报,问题是:
build()
,因为其他每个方法都会返回一个CommandBuilder
Command
子类的实例化主要会变得非常混乱。那么,解决这个问题的最好方法是什么?我曾想过使用接口,但是在我的抽象Command类中,有一些带有“默认”代码的方法,如果子类需要它,它们可以选择覆盖它(但它不是必需的!)这些默认方法利用了Command
类的其他方法,因此我不能将它们作为真正的默认方法重构到接口中。
我的代码工作得很好,我只是觉得用实例化对象的方式,我在某个地方做了一个错误的转弯。对于如何重构或重写我的代码以遵循最佳Java实践,有什么建议吗?
发布于 2017-09-29 08:39:45
也许你应该像这样重构你的build()
:
public <T extends Command> T build(Function<CommandBuilder, T> constructor) {
return constructor.apply(this);
}
这种方式允许构建器接受任何构造函数引用,如
FooCommand cmd = builder.build(FooCommand::new);
另外,您还可以添加适当的代码,以便允许反射。
FooCommand cmd = builder.build(FooCommand.class);
也可以使用,但前者的优点是,如果没有匹配的构造函数,就会出现编译时错误。
https://stackoverflow.com/questions/46484535
复制相似问题