我有一个设计问题。 我有一个读取XML的接口。每个实现者类都读取不同的XML,我想要一种方法来识别我应该为我获得的xml类型动态创建哪个实现者。 问题是java接口不能有静态成员。最好的方法是什么?
示例:
public interface MyXML{
public void readXML(String xml);
public final static String getType();
}
用法:
func(String xml, String type)
{
MyXML obj;
switch(type)
{
case MyImpl.getType():
obj = new MyImpl();
break;
case MyImpl2.getType():
obj = new MyImpl2();
break;
}
obj.readXML(xml);
}
修改 我会尝试更好地解释我想要的东西: 我需要知道哪个xml可以通过哪个实现读取,并且我搜索一种方法来强制任何实现MyXML的人告诉它可以读取哪个xml,所以我不需要在另一个列表或工厂外维护翻译。
答案 0 :(得分:1)
我建议你围绕实例设计你的系统,而不是自己打字。
应用程序将实例化所有XML读取器类型,并将查询每个实例以查找其负责的类型。您可以使用它将XML阅读器组织到一个映射中,并在没有switch或if语句的情况下检索它们。
如果当前设计中有一些重量级资源与某个实例相关联,那么请更改该设计,以便所有资源获取都发生在对象的生命周期中,而不是在构建时。
如果您需要同时使用同一个阅读器的多个实例(例如,在并发设置中),请使用java.util.regex.Pattern
示例的想法及其对应的Matcher
。模式是单线程,一次性匹配器的线程安全工厂。
答案 1 :(得分:0)
看看工厂设计模式。客户端应该调用工厂传递Type,然后工厂返回正确类的实例:
public class MyFactory {
public MyXML createMyXML(Type type) {
return ...
}
}
这样客户就无需知道需要提供哪个具体类。
答案 2 :(得分:0)
在接口中存储实现类型没有意义。界面不应该知道实现。相反,您可以将XML类型存储在枚举中。
enum Type{
TYPE1,
TYPE2;
}
然后,您可以创建一个Map<Type, MyXML>
变量,并在其中添加包含相应Type
的实现。
工厂可以是:
public MyXml getImplementation(String type){
Type type = Type.valueOf(type);
MyXml impl= implementations.get(type);
if(impl == null){
throw new UnsupportedOperationException();//or whatever ex you see fit
}
return impl;
}
答案 3 :(得分:0)
Java只允许接口中的静态常量。在Java 8中,您也可以使用默认实现,但这是另一回事。
解决此问题的一种方法是使getType
正常实例方法,与readXML
相同并提前实例化实现,类似这样的
// somewhere in the constructor or main
List<MyXML> readers = Arrays.asList(new MyImpl1(), new MyImpl2());
public MyXML findReaderForType(String type) {
for (MyXML reader : readers) {
if (reader.getType().equals(type)) {
return reader;
}
}
}
但是,您需要小心设计实现方式,以便可以重复使用。
另一个选择是创建某种静态工厂,它将包含等效的findReaderForType
方法。然后,类型和实现之间的映射包含在此工厂类中。