2016-07-11 7 views
1

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

class MyClass { 
    public MyClass(String arg1, Date arg2, Integer arg3) { 
    // Do something with supplied arguments 
    } 
} 

class MyClassWrapper { 
    private ArrayList<MyClass> objects = new ArrayList<MyClass>(); 
    private final String[] names = {"firstparam","secondparam","thirdparam"}; 
    private final Object[] classes = {String.class,Date.class,Integer.class}; 

    public void addEntry(Map<String, Object> params) { 
    objects.add(new MyClass(
       (String)params.get(names[0]), 
       (Date)params.get(names[1]), 
       (Integer)params.get(names[2]) 
       )); 
    } 

    public ArrayList<MyClass> getEntries() { 
    return objects; 
    } 

    public Object[] getColumnClasses() { 
    return classes; 
    } 

    public String[] getColumnLabels() { 
    return names; 
    } 
} 

Они используется в коде, который считывает данные из внешних источников в HashMap, а затем вызывает addEntry позвонить конструктор MyClass. Я пишу свои собственные классы ***Wrapper, так что мне не нужно добавлять дополнительный конструктор MyClass, чтобы читать Map напрямую.

Все мои ***Wrapper классы выглядят одинаково для имеющих различные names и classes членов, за исключением, и рукописным addEntry. Есть ли способ избежать ручной записи addEntry, чтобы использовать names и classes, чтобы автоматически передавать значения карты в конструктор MyClass?

+0

Да, вы, возможно, могли бы что-то сбручить вместе с отражением. –

+0

@ElliottFrisch Это похоже на то, что можно было сделать во время компиляции (используя дженерики?). Если бы это был C++, я бы ожидал некоторого умного решения метапрограммирования ... – beldaz

+1

Обратите внимание, что доступ к именам параметров с помощью Java 8 становится проще (для поиска их на карте). С более ранними версиями Java вы, вероятно, хотите, чтобы библиотека вам помогла, Spring и другие поддерживают ее (путем чтения и анализа файла .class) –

ответ

0

Вот один для вас решение:

Шаг 1:

Ниже MyClass.java точно так, как указано в вопросе.

public class MyClass { 

private String arg1; 
private Date arg2; 
private Integer arg3; 

public MyClass(String arg1, Date arg2, Integer arg3) { 
     this.arg1 = arg1; 
     this.arg2 = arg2; 
     this.arg3 = arg3; 
    } 

@Override 
public String toString() { 
     return "MyClass [arg1=" + arg1 + ", arg2=" + arg2 + ", arg3=" + arg3 + "]"; 
    } 

} 

Шаг 2:

Теперь создадим класс-оболочку MyClassWrapper.java следующим образом:

import java.lang.reflect.Constructor; 
import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 

public class MyClassWrapper<T> { 
    private List<T> objects = new ArrayList<T>(); 
    private String[] names; 
    private Class<?>[] classes; 
    private Class<T> clazz; 

    public MyClassWrapper(Class<T> clazz, String[] names, Class<?>[] classes) throws Exception { 
     this.clazz = clazz; 
     this.names = names; 
     this.classes = classes; 
    } 

    public void addEntry(Map<String, Object> params) throws Exception { 
     Constructor<T> constructor = clazz.getConstructor(classes); 
     Object[] parameters = new Object[names.length]; 
     for (int i = 0; i < names.length; i++) { 
      parameters[i] = params.get(names[i]); 
     } 
     objects.add(constructor.newInstance(parameters)); 
    } 

    public List<T> getEntries() { 
     return objects; 
    } 

    public Class<?>[] getColumnClasses() { 
     return classes; 
    } 

    public String[] getColumnLabels() { 
     return names; 
    } 
} 

Шаг 3:

Теперь следующий класс MyClassWrapperDemo собирается проверить MyClassWrapper с параметром MyClass. Но вы можете использовать MyClassWrapper с другими классами, похожими на MyClass. Вам не нужно определять другую версию класса-оболочки.

import java.util.Arrays; 
import java.util.Date; 
import java.util.HashMap; 
import java.util.List; 
import java.util.Map; 

public class MyClassWrapperDemo { 
    public static void main(String[] args) throws Exception { 
     MyClassWrapper<MyClass> wrapper= 
       new MyClassWrapper<MyClass>(
       MyClass.class, 
       new String[]{"firstparam", "secondparam", "thirdparam" }, 
       new Class<?>[]{String.class, Date.class, Integer.class} 
       );  
     Map<String, Object> params =new HashMap<String, Object>(); 
     params.put("firstparam", "HelloWorld"); 
     params.put("secondparam", new Date()); 
     params.put("thirdparam", 30); 
     wrapper.addEntry(params); 
     List<MyClass> list= wrapper.getEntries(); 
     String[] lebels = wrapper.getColumnLabels(); 
     Class<?>[] objects= wrapper.getColumnClasses(); 
     System.out.println(list); 
     System.out.println(Arrays.toString(lebels)); 
     System.out.println(Arrays.toString(objects)); 

    } 

} 
+0

Это также хорошее решение. Опять же, похоже, что кто-то отказался от него, не объяснив, почему, что для меня кажется плохим манером. +1 от меня, хотя. – beldaz

+0

Привет, @beldaz, не могли бы вы еще раз взглянуть на мой ответ?Теперь класс 'MyClassWrapper' является действительно параметром, поскольку ему могут назначаться разные имена и члены классов. –

+0

Спасибо, да, похоже, что мне нужно. Не так много между вами и Мэттом, но я соглашусь с вами, поскольку он был опубликован ранее. Было бы полезно узнать, почему кто-то почувствовал необходимость проголосовать за него, но, с моей точки зрения, он выглядит великолепно. – beldaz

0

Мне кажется, что вы хотите шаблон фабрики. Используя отражение, вы можете это сделать. Просто нужны интерфейсы и классы реализации с их собственными поведением. Этот класс, который вы строите, может быть фабрикой.

+1

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

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