Once an interviwer asked me – we know using “instanceof” is bad, can we avoid using it with the help of some pattern (give the name)?
In my 9 years of java programming career I don’t remember that I have used instanceof apart from overriding “equals” method. So first of all this question that “can we avoid its usage with the help of some pattern” made me confuse and I was not able to answer it, later on after doing some reading and trying out some examples I came to the conclusion that its not a right question. Design consideration to avoid “instanceof” in your code totally depend on the problem that you are solving or the requirement you are implementing. Let me explain in detail.
- Is using “instanceof” is bad: Can you avoid its usage when overriding equals method in your java bean? answer is NO. In a situation similar to equals method you cannot avoid its usage, but so far I have not seen any such situation, so presently I think we can avoid its usage apart from equals method, and there is no silver bullet pattern.
- Please read this artical – “http://butunclebob.com/ArticleS.UncleBob.VisitorVersusInstanceOf”, the solution in this article is done using visitor pattern with reflection to avoid “instanceof” usage. What I feel about this solution is that there is no need of visitor and reflection in the solution, however there could be a situation where visitor will help, and my intent here is to show that there is no silver bullet pattern to avoid “instanceof”. The problem mentioned in the above article is – We have courses and we want to generate report about each course, so separate classes are created for courses and course report generators (to achieve separation of concern). The solution provided in the article is trying to identify report generator based on course and then call methods on that report generator to generate report, here the use of reflection with visitor can be easily avoided if we shift data part in course classes (course title, duration, sysRequired, etc) and report generation behaviour in generic report generator or specific report generator. Lets look at generic report generator.
You can see with generic report generator there is no need to check instanceof courses or course report generator, also with the help of builder pattern you can change report structure as required (ex: building report by using only buildTitle and buildBody).
// use course title to generate report title.
Now lets see specific report generator, we can have JavaReportGenerator and AOODReportGenerator, now in solution every time we create a specific report generator we register it (think of Map having course as key and course report generator as value), further we can use factory to return course report generator by providing course to it.
This way we can clearly avoid instanceof and reflection usage as defined in the article above, rather you can see in many situations you can avoid instanceof and reflection using appropriate patterns. Some people think that in case you want to call specific method which was introduced by the sub-class/sub-implementor* needs type checking using “instanceof” (however I think this is wrong as new implementation should go in base class, and sub-classes can avoid this implementation if they want to), but this can be avoided using generics if you are using jdk 5 or above or by using specific report generator implementation.
Some people think “instanceof” introduce lot of if else statement and to avoid that – visitor pattern will help, well I think its wrong, as stated above – refactoring of such code depends on particular implementation, factory, state, builder etc, any pattern can be used depending on the situation. you can even use Predicate (high level pattern**) – please see http://www.infoq.com/presentations/3-Patterns-Cleaner-Code
* in case of interface where you don’t want to break existing implementation by introducing new method in interface.
** pattern mix of several pattern