4

There are two classes X, Y which implement a Base interface There is an interface which takes care of processing the objects of each type

interface Base {
}
class X implements Base {
}
class Y implements Base {
}

interface XProcessor {
    void process(X object);
}
interface YProcessor {
    void process(Y object);
}

But the downside of such approach is that i have to expose one interface for each type of object(X,y..) and if there are many such objects i would end up exposing too many interfaces. I thought i would handle this by exposing just one interface which takes care of processing objects of type Base

interface Processor<E extends Base> {
  void process(E object);
}

The implementer writes his own implementation for processing objects of type X as

class XProcessor implements Processor<X> {
    void process(X object) {
        //do something
    }
}

The problem with such approach is when i have to call the method process, at runtime, i do not know which type of object i should pass to the processor, since at runtime i cannot determine the type of that processor

void process(Processor p) {
    p.process(??);
}

Is there are a better way to handle this problem?

lkamal
  • 3,788
  • 1
  • 20
  • 34

3 Answers3

2

as @tredontho has suggested can use a factory 'ProcessorFactory' like below to get the relevant instance and then call the process method

public class ProcessTest {

    <T extends Base> void processBase(T base) {
        ProcessorFactory.getProcessor(base).process(base);
    }

}


interface Base{
}
class X implements Base{
}
class Y implements Base{
}

interface Processor<E extends Base>{
    void process(E object);
}

interface XProcessor extends Processor<X> {

}
interface YProcessor extends Processor<Y> {

}

class ProcessorFactory {

    @SuppressWarnings("unchecked")
    static <T extends Base> Processor<T> getProcessor(T base) {
        if (base instanceof X) {
            return (Processor<T>) new XProcessorImpl();
        }
        return null;
    }

}

class XProcessorImpl implements XProcessor {

    @Override
    public void process(X object) {
        // TODO Auto-generated method stub

    }

}
Dev Blanked
  • 8,555
  • 3
  • 26
  • 32
  • 1
    This looks clean. However in my case, the interface 'Processor' will be exposed to the user and he'll implement it. At runtime, we'll get all the classes which implement 'Processor' interface and call their 'process' method. So again, unless we have an interface for each type of object like 'XProcessor' for objects of type 'X', there is no way to figure out which type of object to pass to the process method at runtime. So in my case, i think a single generic interface would not be sufficient and i should expose an interface for each type of object. – themanwhosoldtheworld Oct 09 '13 at 06:55
  • 1
    @Kalyan you could introduce 'Class getSupportedClass();' to the Processor interface and force implementers of the interface to expose the supported class. By using this you could figure out which implementation of Processor to use for a given Base instance – Dev Blanked Oct 09 '13 at 09:25
  • hmm, that shud be good, although it doesnt look very elegant. – themanwhosoldtheworld Oct 09 '13 at 09:30
1

This has nothing to do with runtime. You have already removed the type at compile time if you write something like

void process(Processor p){
  p.process(??);
}

If your Processor interface is generic you should not use the raw type anymore:

<E extends Base> void process(Processor<E> p){
  p.process(…instance of E…);
}

For example:

<E extends Base> void processAll(Processor<E> p, Collection<? extends E> c){
  for(E item: c) p.process(c);
}
Holger
  • 285,553
  • 42
  • 434
  • 765
1

Does process() method have to have a parameter?

Can you possibly go in the following way?

Each individual class implements common interface processor that includes a stub for void process() method, thus creating their custom action.. Then you can upcast your objects to the interface (put them in some sort of collection if so required).

You can have something like:

List<Processor> p = new ArrayList<>();
p.add(new Xprocessor);
p.add(new Yprocessor);

for each(Processor pr: p) {
   pr.Processor();
}

and polymorphism will to take care of the rest.

In such case you would not even need generics.

PM 77-1
  • 12,933
  • 21
  • 68
  • 111