2015-10-05 4 views
0

У меня есть ситуация, когда у меня есть два разных объекта, которые выполняют в основном одно и то же, но имеют разные API.Java: Как относиться к двум различным объектам, тем же, с тем же кодом?

Если бы я мог обращаться с ними одинаково, я мог бы использовать один метод, чтобы позаботиться обо всех них.

В принципе, мне нужно выполнить итерацию с помощью цикла for. Эти два объекта имеют разные функциональные имена для получения размера и retriving последнего результата внутри каждого:

CustomUnMutableObj1.getMySize() CustomUnMutableObj2.getTotal()

CustomUnMutableObj1.getlastresult() CustomUnMutableObj2.getlastvalue()

В любом случае я могу использовать то же самое для цикла для обоих, без большого неуклюжего набора условных выражений, и иметь код, слепой относительно типа объекта?

+3

Если имеет смысл сделать это, оба класса реализуют общий интерфейс. – sstan

+0

Я предполагаю, что ваши настоящие имена более приятны, чем 'CustomUnMutableObj1' – immibis

ответ

0

Если вы не можете изменить эти два класса в вопросе так они реализуют общий интерфейс, вы можете все еще получить тот же эффект, написав несколько «адаптер класса»:

interface CustomObjInterface { 
    int getSize(); 
    int getLatestResult(); 
} 

class CustomUnMutableObj1Adapter implements CustomObjInterface { 
    private CustomUnMutableObj1 wrapped; 
    public CustomUnMutableObj1Adapter(CustomUnMutableObj1 wrapped) { 
     this.wrapped = wrapped; 
    } 
    @Override int getSize() {return wrapped.getMySize();} 
    @Override int getLatestResult() {return wrapped.getTotal();} 
} 

// and a similar class for CustomUnMutableObj2 

, а затем использовать адаптеры вместо исходных объектов:

void doStuff(CustomObjInterface obj) { 
    // do stuff with obj here, using getSize and getLatestResult 
} 

// call it like this, for a CustomUnMutableObj1 
// If you had a CustomUnMutableObj2, you'd use a CustomUnMutableObj2Adapter instead 
doStuff(new CustomUnMutableObj1Adapter(obj)); 
0

что-то, что неясно: вы сказали, «итерацию через либо используя для цикла», это означает, что ваш метод получения либо Collection<Obj1> или Collection<Obj2>, но не Collection<Object>, который будет содержать как Obj1, так и Obj2? (Мой ответ основывается на приведенном выше предположении)

IMHO, используя адаптер (как предложено в другом ответе), может быть не лучшим выбором для вышеуказанного случая, потому что, если вы проходите в List<Obj1>, вам необходимо построить List<CustomUnMutableObj1Adapter> и перейдите к вашему «общему методу обработки», для которого вам по-прежнему нужна куча кода для его обработки, и вы создадите один список адаптеров + один адаптер для каждого элемента для каждого вызова логики процесса, что может быть не очень хорошо.

Конечно, лучший способ решить - ввести общий интерфейс/суперкласс, чтобы дать этим операциям значимую концепцию. Однако, если это не выбор, вы можете увидеть, поможет ли вам следующее.

Один из способов уменьшить код котельной пластины является использование что-то похожее на метод шаблона (Если вы знакомы с Spring, есть много подобного шаблона, как это)

например (Псевдо-код, не компилируется)

interface ProcessInfoExtractor<T> { 
    int getSize(T entity); 
    String getLastValue(T entity); 
} 

выше интерфейс будет нести ответственность, чтобы выполнить «общую» операцию против указанного объекта.

Затем сделайте свой метод обработки, как это:

void <T> process(Collection<? extends T> entities, ProcessInfoExtractor<T> infoExtractor) { 
    for (T entity : entites) { 
     System.out.println("size " + infoExtractor.getSize(entity) 
         + " last value " + infoExtractor.getLastValue(entity)); 
    } 
} 

так, когда вам нужно перебирать через в List<Obj1>, просто сделать:

process(obj1List, 
     new ProcessInfoExtractor<Obj1> (
      @Override 
      int getSize(Obj1 obj1) { return obj1.getMySize(); } 
      @Override 
      String getLastValue(Obj1 obj1) { return obj1.getLastResult(); } 
     )); 

(Аналогичный случай для Obj2)

Для легкость вызова, вы можете сделать 2 метода обертки, которые внутренне вызывают вышеуказанный метод process, например

void process(Collection<Obj1> obj1List) { 
    process(obj1List, obj1InfoExtractor); // assume extractor is stateless, 
              // you can create one and reuse it 
}; 

void process(Collection<Obj2> obj2List) { 
    process(obj2List, obj2InfoExtractor); // assume extractor is stateless, 
              // you can create one and reuse it 
}; 
Смежные вопросы