2013-11-08 4 views
0

Мне нужно расширить алгоритм, который широко использует шаблон двойной отправки.Java-отправка и общая информация Java

Этот алгоритм управляет несколькими различными классами данных (много классов), и для каждого класса требуется одно и то же расширение.

Я не хочу изменять существующие классы данных (для ограничения проблем сериализации), а также класс алгоритма (для ограничения регрессий). Поэтому я разработал решение, используя новые классы.

Я хочу использовать что-то вроде следующего примера, но java отказывается распознавать мои типы.

import Main.Data1; 
import Main.ExtendedData; 

public class Main 
{ 
    static interface OperatorDispatcher 
    { 
    void dispatchDoSomething(OperatorDispatch operator); 
    } 

    static class Data1 implements OperatorDispatcher 
    { 
    @Override 
    public void dispatchDoSomething(OperatorDispatch operator) 
    { 
     operator.doSomething(this); 
    }  
    } 

    static class Data2 implements OperatorDispatcher 
    { 
    @Override 
    public void dispatchDoSomething(OperatorDispatch operator) 
    { 
     operator.doSomething(this); 
    }  
    } 

    static interface OperatorDispatch 
    { 
    void doSomething(Data1 data); 
    void doSomething(Data2 data); 
    } 

    static class MyOperator implements OperatorDispatch 
    { 
    public void doSomething(Data1 data1) 
    { 
     System.out.println("doSomething with Data1 : " + data1); 
    } 

    public void doSomething(Data2 data2) 
    { 
     System.out.println("doSomething with Data2 : " + data2); 
    } 
    } 

    static interface ExtendedOperatorDispatch 
    { 
    void doSomething(Data1 data, Object extension); 
    void doSomething(Data2 data, Object extension); 
    } 

    static class MyExtendedOperator implements ExtendedOperatorDispatch 
    { 
    public void doSomething(Data1 data1, Object extension) 
    { 
     System.out.println("doSomething with Data1 : " + data1 + " and " + extension); 
    } 

    public void doSomething(Data2 data2, Object extension) 
    { 
     System.out.println("doSomething with Data2 : " + data2 + " and " + extension); 
    } 
    } 

    static interface ExtendedOperatorDispatcher extends OperatorDispatcher 
    {   
    void dispatchDoSomething(ExtendedOperatorDispatch operator); 
    } 

    /* 
    * I don't want to specialize this class for each data type. 
    */ 
    static class ExtendedData<T> implements ExtendedOperatorDispatcher 
    { 
    T _data; 
    Object _extension; 

    public ExtendedData(T data, Object extension) 
    { 
     _data = data; 
     _extension = extension; 
    } 

    @Override 
    public void dispatchDoSomething(OperatorDispatch operator) 
    { 
     /* 
     * ERROR : The method doSomething(Main.Data1) in the type Main.OperatorDispatch is not applicable for the arguments (T) 
     */ 
     operator.doSomething(_data); 
    } 

    @Override 
    public void dispatchDoSomething(ExtendedOperatorDispatch operator) 
    { 
     /* 
     * ERROR : The method doSomething(Main.Data1, Object) in the type Main.ExtendedOperatorDispatch is not applicable for the arguments (T, Object) 
     */ 
     operator.doSomething(_data, _extension); 
    }  
    } 

    public static void main(String[] args) 
    { 
    MyOperator operator = new MyOperator(); 

    Data1 data10 = new Data1(); 
    data10.dispatchDoSomething(operator); 

    Data1 data11 = new Data1(); 
    data11.dispatchDoSomething(operator); 

    Data2 data20 = new Data2(); 
    data20.dispatchDoSomething(operator); 

    MyExtendedOperator extendedOperator = new MyExtendedOperator(); 

    ExtendedData<Data1> extendedData10 = new ExtendedData<Data1>(data10, "EXTENSION"); 
    extendedData10.dispatchDoSomething(operator); 
    extendedData10.dispatchDoSomething(extendedOperator); 

    ExtendedData<Data2> extendedData20 = new ExtendedData<Data2>(data20, "EXTENSION"); 
    extendedData20.dispatchDoSomething(operator); 
    extendedData20.dispatchDoSomething(extendedOperator);  
    } 
} 

Вы знаете, как исправить это или подумать о другом решении, не стесняйтесь отвечать.

Спасибо-х

+0

Да, это не сработает. –

+0

@Louis Есть идеи? – user2970188

+0

Ну, дженерики не могут сделать этого, потому что стирание типа и другие решения используют отражение. – user2970188

ответ

0

Это будет делать трюк, но может быть более простым решением. Для отправки, отражение может быть использовано, если производительность не имеет решающего значения. Обратите внимание, что для работы должен работать только один совместимый метод.

class ExtendedData<T> implements ExtendedOperatorDispatcher { 
    T _data; 
    Object _extension; 
    private Class<? extends Object> _dataClass; 
    private Class<? extends Object> _extensionClass; 

    public ExtendedData(T data, Object extension) { 
     _data = data; 
     _extension = extension; 
     _dataClass = (_data == null ? Object.class : _data.getClass()); 
     _extensionClass = (_extension == null ? Object.class : _extension 
       .getClass()); 
    } 

    @Override 
    public void dispatchDoSomething(OperatorDispatch operator) { 
     try { 
      Method foundMethod = null; 
      for (Method method : operator.getClass().getMethods()) { 
       Class<?>[] params = method.getParameterTypes(); 
       if ("doSomething".equals(method.getName()) 
         && params.length == 1) 
        if (params[0].isAssignableFrom(_dataClass)) { 
         if (foundMethod == null) 
          foundMethod = method; 
         else 
          throw new IllegalArgumentException(
            "Multiple method can be called"); 
        } 
      } 
      foundMethod.invoke(operator, _data); 
     } catch (SecurityException | IllegalAccessException 
       | IllegalArgumentException | InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void dispatchDoSomething(ExtendedOperatorDispatch operator) { 
     try { 
      Method foundMethod = null; 
      for (Method method : operator.getClass().getMethods()) { 
       Class<?>[] params = method.getParameterTypes(); 
       if ("doSomething".equals(method.getName()) 
         && params.length == 2) 
        if (params[0].isAssignableFrom(_dataClass) && params[1].isAssignableFrom(_extensionClass)) { 
         if (foundMethod == null) 
          foundMethod = method; 
         else 
          throw new IllegalArgumentException(
            "Multiple method can be called"); 
        } 
      } 
      foundMethod.invoke(operator, _data, _extension); 
     } catch (SecurityException | IllegalAccessException 
       | IllegalArgumentException | InvocationTargetException e) { 
      e.printStackTrace(); 
     } 
    } 
} 
+0

Интересно, спасибо. В любом случае, чем больше я ищу решение, тем больше думаю, что я напишу много класса вместо общего. – user2970188

+0

Написание много классов, чтобы сделать небольшую работу бесполезно. Этот пример кода обеспечивает решение вопроса, но я думаю, что лучшее моделирование, вероятно, может решить вашу проблему без большого количества кода и не отражения. – sebtic

+0

Я чувствую себя в ловушке от ограничений на Java. – user2970188

Смежные вопросы