我正在设计一个选项分配框架。
我构建了一个选项类:
string str = "Test123(45)";
string[] delimiters ={@"("};;
string[] split = str.Split(delimiters, StringSplitOptions.None);
var b=split[0]+"()";
对于每个需要用户输入选项的模块,它都有一个静态方法:
public class MyOptionModule {
public MyOptionModule() {
}
public void addOption(String option, String explanation) {
//...
}
public void printHelp() {
//...
}
public void parse(String[] args) {
//...
}
}
在更复杂的情况下,某些模块可能包含其他模块。这是一个例子:
public static void assignOptions(MyOptionModule optionModule) {
optionModule.addOption("o", "Some options");
}
示例的帮助菜单:
class ReaderClass {
public static void assignOptions(MyOptionModule optionModule) {
optionModule.addOption("i", "Input file for reader");
}
}
class WriterClass {
public static void assignOptions(MyOptionModule optionModule) {
optionModule.addOption("o", "Output file for reader");
}
}
public class OutClass {
public static void assignOptions(MyOptionModule optionModule) {
optionModule.addOption("x", "Some other options in Out Class");
optionModule.addOption("y", "Some other options in Out Class");
optionModule.addOption("z", "Some other options in Out Class");
}
public static void main(String[] args) {
MyOptionModule optionModule = new MyOptionModule();
ReaderClass.assignOptions(optionModule);
WriterClass.assignOptions(optionModule);
OutClass.assignOptions(optionModule);
if (args.length == 0) {
optionModule.printHelp();
}
optionModule.parse(args);
}
}
现在我的问题是我的程序被给了一些未知的模块,我想调用它们的assignOptions。
/*
======== The help menu ========
i: Input file for reader
o: Output file for reader
x: Some other options in Out Class
y: Some other options in Out Class
z: Some other options in Out Class
*/
虽然可以使用反射,但如果我可以检查某个类是否实现了assignOptions方法,那将会很棒。 assignOptions应该是静态的,因为类实例与要分配的选项无关。但是,我们不能使用静态方法的接口来进行这样的指示(已经进行了很多讨论)。那么有什么设计可以避免反射,而我们无法在界面中获得静态方法?谢谢!
答案 0 :(得分:2)
没有。您将不得不使用反射或接口和实例。
如果工具实例与选项无关,为什么不将两者分开?
OptionModule.java:
public interface OptionModule {
void assignOptions(MyOptionsModule optionsModule);
}
MyOptionsModuleFactory.java:
public class MyOptionsModuleFactory {
public static void createOptionsModule(Consumer<MyOptionsModule>... modules) {
MyOptionsModule optionsModule = ...
for(Consumer<MyOptionsModule> module : modules) {
module.accept(optionsModule);
}
}
}
CustomToolModule.java:
public class CustomToolModule {
public static class Options implements OptionsModule {
void assignOptions(MyOptionModule optionModule) {
...
}
}
public static void main(String[] args) {
MyOptionsModule optionsModule = MyOptionsModuleFactory.createOptionsModule(
new CustomToolModule.Options()
);
}
}
如果您使用的是Java 8,则可以使用方法引用来完成类似于您想要的操作:
CustomToolModule.java:
public static class CustomToolModule {
public static void assignOptions(MyOptionsModule optionsModule) {
...
}
public static void main(String[] args) {
MyOptionsModule optionsModule = MyOptionsModuleFactory.createOptionsModule(
CustomToolModule::assignOptions,
CustomToolModule2::assignOptions
);
...
}
}
答案 1 :(得分:0)
除了反思或使用本机代码之外,在保留方法static
时,我想不出任何方法可以使这项工作。
(在Java 8中,您确实可以在接口中声明static
方法,但是您无法在实现类中覆盖它们。)
但是,既然你问是否有任何设计来避免这种情况,那么可以:Factories。
我假设你熟悉它们,所以长话短说:
您可以将Class
及其所有静态成员转换为工厂类的实例,然后可以使用该界面。
建立像
public class ExampleFactory
{
public static final ExampleFactory INSTANCE = new ExampleFactory();
private ExampleFactory(){}
public Example newExample(){ /* ... */ }
}
可能是你能得到的最接近你的要求
你有一个额外的类,你必须实例化像ExampleFactory.INSTANCE.newExample()
而不是new Example()
的实例,但就是这样。