Question

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?

Was it helpful?

Solution

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

    }

}

OTHER TIPS

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);
}

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top