2015-02-11 12 views
2

У меня есть proyect, который вызывает различные веб-службы, используя внешнюю библиотеку. Эта библиотека дает мне такие объекты, как это:Java: идентичные объекты, как избежать дублированного кода

public static class ObjA { 
    @XmlElement(name = "counter", required = true) 
    protected BigInteger counter; 
    @XmlElement(name = "data", required = true) 
    protected String data; 
    [...] 
} 

и это:

public static class ObjB { 
    @XmlElement(name = "counter", required = true) 
    protected BigInteger counter; 
    @XmlElement(name = "data", required = true) 
    protected String data; 
    [...] 
} 

как вы можете видеть objA и objB имеют одинаковые свойства, поэтому, если я должен использовать оба, Я дублировать код :

public class myClass { 

    [...] 
    private ObjA a; 
    private ObjB b; 
    [...] 

    public void myClass() { 
     [...] 
     this.a = new ObjectFactory().createObjA(); 
     this.b = new ObjectFactory().createObjB(); 
     [...] 
    } 

    public void init() { 
     this.initA(); 
     this.initB(); 
    } 

    private void initA() { 
     this.a.setCounter(BigInteger.ZERO); 
     this.a.setData = ""; 
    } 

    private void initB() { 
     this.b.setCounter(BigInteger.ZERO); 
     this.b.setData = ""; 
    } 

    [...] 
} 

Inita и INITB идентичны, я не могу получить доступ к коду библиотеки, так что я не могу создать общий интерфейс, каким образом я могу избежать дублированного кода? Я имею в виду, что возможно иметь что-то вроде этого?

private void initObj([ObjA|ObjB] obj) { 
     obj.setCounter(BigInteger.ZERO); 
     obj.setData = ""; 
    } 

Спасибо! Большое спасибо!

добавление

Пожалуйста, обратите внимание, у меня нет доступа к основной библиотеке, поэтому я не могу добавить модифицировать классы, интерфейсы, WSDL или XSD каким-либо образом. Кроме того, на мой взгляд, не важно, если я использую WS или нет, JAXB или другую библиотеку: вы можете себе представить ObjA и ObjB без аннотаций, как это:

public static class ObjA { 
    protected BigInteger counter; 
    protected String data; 
    [...] 
} 

public static class ObjB { 
    protected BigInteger counter; 
    protected String data; 
    [...] 
} 

и суть дела Безразлично» t изменение.

+0

Если вы не можете создать общий интерфейс (в данном случае абстрактный класс), вам придется написать код для инициализации типа 'ObjA' и тип' ObjB' независимо от того, что вы делаете. – EpicPandaForce

+0

Вы можете использовать динамический подход (отражение или BeanUtil) для работы с разными типами с помощью того же метода. Однако у этого есть ряд собственных проблем (статический анализ не знает об этом), поэтому я обычно избегаю этого. Мы ничего не знаем об этом контексте, поэтому могут быть и другие решения. И не забудьте поговорить с поставщиком API. – eckes

+0

Я бы просто сделал супер класс, вручную отредактировал сгенерированный (угадайте его только одно место на класс), затем зачитайте меня и видео о том, что и почему сделали. – tgkprog

ответ

1

Я предполагаю, что классы генерируются для вас с помощью какого-то инструмента, возможно, Maven CXF-Codegen-плагина и т.д. Если это так, то вам нужно изменить WSDL и XSD-х так что классы DTO генерируются для вашего удовлетворения. Если WSDL был предоставлен вам, вам просто нужно принять сервис как есть?

Вы можете использовать отражение, если знаете, что общие методы имеют одно и то же имя?

так вы могли бы сделать что-то подобное с сырым отражения:

import java.lang.reflect.Method; 
import java.math.BigInteger; 
import java.util.ArrayList; 
import java.util.List; 

public class Test {  
    public static void initObject(Object o) throws Exception { 
     if (!(o instanceof ObjA)&&!(o instanceof ObjB)) return; 
     Method m = o.getClass().getMethod("setCounter",java.math.BigInteger.class); 
     m.invoke(o,BigInteger.ZERO); 
     m = o.getClass().getMethod("setData",java.lang.String.class); 
     m.invoke(o,""); 
    } 

    public static void main(final String[] args) throws Exception { 
     List<Object>objects = new ArrayList<Object>(); 
     //this is like your factory method 
     Object o = Class.forName("ObjA").newInstance(); 
     initObject(o); 
     objects.add(o); 
     o = Class.forName("ObjB").newInstance(); 
     initObject(o); 
     objects.add(o); 
    } 
} 

Если вы хотите использовать библиотеку вы могли бы использовать что-то вроде JXPath и see docs here Но я думаю, что для вашей цели сырье отражение, вероятно, хорошо , Нет необходимости в массовой библиотеке отражения.

+0

Я не могу изменить WSDL или XSD. Я рассматриваю размышления, но, как заявил @ L.Butz, это плохая практика. –

+0

Обычно это плохая практика, просто потому, что это сложно сделать правильно. Но отражение фактически используется практически во всех основных java-библиотеках, которые вы выбираете, особенно в Jackson и т. Д. Я не могу думать о какой-либо возможности вашей проблемы, которая не предполагает какого-либо решения на основе отражения. Вы можете попробовать что-то вроде xpath, чтобы сделать обновление для вас http://commons.apache.org/proper/commons-jxpath/ – Richard

+0

Я думаю, что вы правы. Вы отправите ответ на примере, который разрешит проблему с ObjA и ObjB, чтобы я мог в конце концов принять его? –

0

Поскольку у них нет общего интерфейса (или родительского класса?), Я предполагаю, что путь к нему - это отражение Java.

Создайте некоторые вспомогательные методы отражения как «init (Class clazz)» и вызовите конструкторов.

Помните, что в большинстве случаев отражения в java - это плохая практика, поэтому убедитесь, что для достижения вашей цели нет других/лучших методов.

+0

Технически выполнимо, но когда я пытаюсь представить подписи «вспомогательных методов» и результирующего кода, я дрожу, деликатно. И проверка времени компиляции будет отложена до времени выполнения. – laune

1

Я полагаю, что вы используете JAXB. Вы можете прочитать список объектов. Посмотреть этот пост: JAXB Unmarshalling: List of objects

+0

Как это избежать дублирования кода, как в myClass OP? Пожалуйста, объясни! – laune

+0

Это не список объектов, они являются два одинаковых объекта, но определяется с двумя именами, это как с мою lillte книгу мой хороший фильм: bookdata и filmdata являются идентичными, но разными объектами –

+0

Чтобы обеспечить лучшую помощь, вы должны предоставить больше информации, чтобы решить эту проблему, например: используете ли вы JAXB? Вы вызовете 1 webservice, и с этим ответом вы будете строить объекты A и B? Или они получат информацию от разных ws-сумов? – PSA

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