2015-02-23 2 views
1

У меня вопрос дизайна. У меня есть интерфейс, который читает XML. Каждый класс-разработчик читает разные XML-файлы, и я хочу, чтобы определить, какой разработчик должен я динамически создавать для xml-типа, который я получаю. Проблема в том, что интерфейс java не может содержать статические элементы. Каков наилучший способ сделать это?Что является альтернативой статическому в интерфейсе 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); 
    } 

EDIT: Попробую лучше объяснить, что я хочу: мне нужно знать, какие XML можно прочитать с помощью которого и я ищу способ заставить любого, кто реализует MyXML, указать, какой xml он может читать, поэтому мне не нужно поддерживать перевод за пределами другого списка или фабрики.

+1

«MyImpl.getType()» должен быть постоянным и динамически не оцениваться во время выполнения. – SMA

+0

Что значит: интерфейс Java не может содержать статические элементы? Все переменные в интерфейсе являются статическими. – Stultuske

+0

Stultuske: public final static String getType(); не подходит для компиляции. – user3369398

ответ

0

Взгляните на шаблон фабричного дизайна. Клиент должен позвонить на завод проходящего типа, то завод возвращает экземпляр соответствующего класса:

public class MyFactory { 
    public MyXML createMyXML(Type type) { 
     return ... 
    } 
} 

Таким образом, клиент свободен от Обязанности знать, какие конкретный класс должно быть обеспечено.

0

Нет смысла хранить типы реализации в интерфейсе. Интерфейс не должен знать о реализации. Вместо этого вы можете сохранить XML-тип в Enum.

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; 
} 
+0

Это система, закрытая для расширения. Если во время компиляции известны все типы, достаточно просто использовать каждый такой тип в инструкции 'switch'. В обоих случаях дизайн предполагает, что вы полностью контролируете все типы считывателей XML, поэтому легко убедиться, что каждая из них имеет статическую переменную. –

1

Я предлагаю вам разработать систему вокруг экземпляров, не сами типы.

Приложение создаст экземпляр всех типов чтения XML и будет запрашивать каждый экземпляр для типа, которым он отвечает. Вы можете использовать это, чтобы упорядочить читатели XML на карте и получить их без каких-либо переключателей или if-statements.

Если в вашем текущем проекте есть какие-то тяжеловесные ресурсы, связанные с экземпляром, то измените этот проект таким образом, чтобы все приобретение ресурсов происходило позже в жизненном цикле объекта, а не во время строительства.

Если вам нужно несколько экземпляров одного и того же считывателя одновременно (например, в параллельной настройке), используйте идею, приведенную в качестве примера, с помощью java.util.regex.Pattern и ее соответствующих Matcher. Образец представляет собой нитевидную фабрику однопоточных одноразовых соединителей.

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. Тогда отображение между типом и реализацией содержится в этом заводском классе.