Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I have the following type hierarchy:

interface I:
    ----+class B implements I
    ----+class C implements I
    ----+class D implements I

I have another class Consumer1 that supports types C and D but not B (in its various methods) and a class Consumer2 that supports type B. I have total control over Consumer1 and Consumer2 so I can choose how to implement them. Now, at runtime I expect my callers to give me a collection of Is and I will decide internally whether to route them to Consumer1 or Consumer2.

Now, a very bad non-OOP way is to do an if instanceof check all over the place and mess things up. One alternative is to register a supporting class Map<Class<?>, Class<?>> that shall contain {{B,Consumer2}, {C,Consumer1}, {D,Consumer1}}. This is as bad as the previous one because I shall have to cast objects after figuring out whether to send them to Consumer1 or Consumer2.

A second alternative is to apply a Visitor pattern which would solve this rather neatly but prevent my interface from being extended further (unless I modify the visitor). Is there a neater alternative?

share|improve this question
    
It's really hard to follow this with all the B's, C's, D's, E's and F's. –  Rein Henrichs Apr 1 '13 at 3:27
    
@ReinHenrichs Thanks. I gave them some meaningful names but the essence of the problem is that I want to filter a collection of objects based on what run time type they have. –  Monster Truck Apr 1 '13 at 3:32
3  
Respectfully, if you have classes implementing an interface that require separate consumers, perhaps the interface should be split in two? Practically, maybe you can use Chain of Responsibility; if(consumer1.canConsume(x)){ consumer1.consume(x); }else if(consumer2.canConsume(x)){ consumer2.consume(x); }? –  John Cartwright Apr 1 '13 at 4:55
    
@John I entertained that possibility. But then how will canConsume() identify if it can consume a given type? Will it maintain a map of supported classes or use instanceof? I.e., the same problem again. –  Monster Truck Apr 1 '13 at 4:57
    
@MonsterTruck It could decide with a map, yes, or based on some properties of the interface, like which optional methods are implemented or the return value of boolean getter methods. What are Consumer1 and Consumer2 doing differently? And what separates C and D from B? –  John Cartwright Apr 1 '13 at 5:02

3 Answers 3

I think Chain of responsibility is best fit for this problem. This will make it properly extensible, while encapsulating eventual instanceof calls into the consumer themselves.

To add to this. I don't think using instanceof is wrong. It just needs to be properly encapsulated, just like in this case.

share|improve this answer

Consider the acyclic visitor pattern. It allows extensions to the hierarchy without necessarily impacting all the visitors (only the ones that need to visit all objects, which don't seem to be present in your design).

Alternatively, I think it's not a problem to have the type checks in the consumer themselves, since they'll be concerned with checking only the types that they work with (not that different from the acyclic visitors). Then you could either dispatch the Is to all consumers and only the ones that really care about the runtime type will do anything with them, or you could do it in a chain of responsibility style, as already suggested in the comments by John Cartwright.

share|improve this answer

Why is consumers not able to do their work with just I interface? Consumers should require instances of I, not rely on specifics of B,C or D.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.