首先,抱歉我的措辞不完整,如果有不清楚的地方,请告诉我。
在构建java应用程序的类结构时,我想知道在我的案例中是否存在我尚未发现的已知最佳实践。
例如,有A,B,C和更多类指定设备类型,每个设备都有一个标记器,解析器和编译器。
首先,我有四个这样的接口。
interface Device {
public void x();
public int y();
public String z();
...
}
interface Tokenizer {...}
interface Parser {...}
interface Compiler {...}
而且,实际的具体类是,
public class ADevice implements Device {...}
public class BDevice implements Device {...}
public class CDevice implements Device {...}
class ATokenizer implements Tokeninzer {...}
class BTokenizer implements Tokeninzer {...}
class CTokenizer implements Tokeninzer {...}
class AParser implements Parser {...}
...
class ACompiler implements Compiler {...}
...
此外,重要的是,"设备"类及其接口是公共的,因此将包含在存根lib中。其他任何内容只会包含在实际的库中,并且对于通过引用API生成脚本的用户不可见。
如何实现每种类型及其相应接口之间的内聚。
更详细地说,是否有一种方法可以确定它们是否在编译时在每种类型的设备接口与其对应的标记化器,解析器或编译器接口之间是否正确配对?
例如,有一个使用" Device"的经理类。对象和" Tokenizer"," Parser"和"编译器"对象。如你所见," ADevice"对象只能与" ATokenizer"," AParser"或" ACompiler"配对。但是,如果我们从界面定义设备对象的类型,那么我们无法判断这些对象是否对应于正确的" Tokenizer"," Parser",或者"编译"对象,除了" instanceOf"操作员在运行时间。 例如," ADevice"可以匹配" BTokenizer"," CParser"等等,这不会产生编译错误。
我希望我能听到一个好的答案或重定向参考。
答案 0 :(得分:0)
您是否考虑过通用接口?
使用如下界面:
public interface Parser<E extends Device> {
void parse(E device);
void parse(String someString);
}
您可以像这样创建类:
public class AParser implements Parser<ADevice> {
@Override
public void parse(ADevice device) {
//parse...
}
@Override
void parse(String someString) {
//parse...
}
}
答案 1 :(得分:0)
一种解决方案是对接口进行参数化:
interface Tokenizer<D extends Device> { ... }
interface Parser<D extends Device> { ... }
interface Compiler<D extends Device> { ... }
然后你的实现将是:
class ATokenizer implements Tokeniser<ADevice> { ... }
class BTokenizer implements Tokenizer<BDevice> { ... }
class CTokenizer implements Tokenizer<CDevice> { ... }
class AParser implements Parser<ADevice> { ... }
.
.
.
class ACompiler implements Compiler<ADevice> { ... }
然后,您可以在Manager
类中使用一种方法将它们限制为相同的类型:
public <D extends Device> void doStuff(Tokeizer<D> tokenizer, Parser<D> parser, Compiler<D> compiler) { ... }
编译器只允许在你描述时使用它:
doStuff(new ATokeizer(), new AParser(), new ACompiler()); // works
doStuff(new ATokeizer(), new AParser(), new BCompiler()); // compiler error