Passing a list of base class objects to a method and using instanceof to filter











up vote
-1
down vote

favorite












I'm working on a Java reverse engineering project, where I am analyzing bytecode and trying to identify classes, methods and fields using the ASM framework. After identifying these I transform some classes to implement my custom interfaces with, e.g., getter methods.



For identifying classes, I have created an abstract class Analyzer with an abstract method for running the analysis on a collection of classes. Child classes of Analyzer try to identify a certain class/field/method of interest. For instance, AnimalAnalyzer attempts to identify the class which represents an animal.



After running the analyzers, I inject my own interfaces and their implementations into the classes. Similarly to Analyzer, I have created an Injector interface with an inject(List<Analyzer> analyzers) method. For each class that I want to inject there is a separate class which implements the interface, e.g., AnimalInjector. The injector iterates the list of Analyzers, which contain the results of their analysis, and uses the relevant ones by checking their type with the instanceof operator. By "relevant ones" I mean the analyzers which contain the information needed to generate the bytecode with.



public abstract class Analyzer {    
public abstract void run(ClassCollection classCollection);
}

public class AnimalAnalyzer extends Analyzer {
private ClassNode identifiedClass = null;
@Override
public void run(ClassCollection classCollection) {
for (ClassNode classNode : classCollection.getAllClassNodes()) {
boolean isMatch = doesClassMatch(classNode); // method omitted from example
if (isMatch) {
identifiedClass = classNode;
break;
}
}
}
}




public interface Injector {
void inject(List<Analyzer> analyzers);
}

public class AnimalInjector implements Injector {
@Override
public void inject(List<Analyzer> analyzers) {
AnimalAnalyzer animalAnalyzer = null;
for (Analyzer analyzer : analyzers) {
if (analyzer instanceof AnimalAnalyzer) {
animalAnalyzer = (AnimalAnalyzer) analyzer;
}
}
if (animalAnalyzer == null) {
throw new IllegalStateException("AnimalAnalyzer not found in list");
}
... (bytecode generation and injection)
}
}


One of the reasons that I chose to do it this way is that the analyzers have to be run in a specific order. For example, to identify a Dog which extends Animal, the latter has to be found first. For this purpose I created MasterAnalyzer, which stores a list of the analyzers in a specific order. When run is invoked on this analyzer, it calls run on the analyzers in the list in the right order.



public class MasterAnalyzer extends Analyzer {
private List<Analyzer> analyzers = new ArrayList<>();

public MasterAnalyzer() {
analyzers.add(new AnimalAnalyzer());
analyzers.add(new DogAnalyzer());
... (more analyzers)
}

public List<Analyzer> getAnalyzers() {
return analyzers;
}

@Override
public void run(ClassCollection classCollection) {
for (Analyzer analyzer : analyzers) {
analyzer.run(classCollection);
}
}
}


The injectors, in turn, can all be run with the same command: inject(masterAnalyzers.getAnalyzers()). While this makes it easy at the client side, it causes the injectors to know more than they need to know. For instance, let's assume that we also have a CatAnalyzer. Now, when we run the DogInjector, the list of analyzers will include the CatAnalyzer, even though the DogInjector does not care about it. This, along with the nasty instanceof usages, causes red signals to me. Now I am reaching out to you more experienced developers for some tips on how to improve my design. While searching for alternative ways, I found the Visitor pattern, which could be applicable here. However, I am still unsure how to apply it and whether it would improve my design or not.










share|improve this question







New contributor




Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
























    up vote
    -1
    down vote

    favorite












    I'm working on a Java reverse engineering project, where I am analyzing bytecode and trying to identify classes, methods and fields using the ASM framework. After identifying these I transform some classes to implement my custom interfaces with, e.g., getter methods.



    For identifying classes, I have created an abstract class Analyzer with an abstract method for running the analysis on a collection of classes. Child classes of Analyzer try to identify a certain class/field/method of interest. For instance, AnimalAnalyzer attempts to identify the class which represents an animal.



    After running the analyzers, I inject my own interfaces and their implementations into the classes. Similarly to Analyzer, I have created an Injector interface with an inject(List<Analyzer> analyzers) method. For each class that I want to inject there is a separate class which implements the interface, e.g., AnimalInjector. The injector iterates the list of Analyzers, which contain the results of their analysis, and uses the relevant ones by checking their type with the instanceof operator. By "relevant ones" I mean the analyzers which contain the information needed to generate the bytecode with.



    public abstract class Analyzer {    
    public abstract void run(ClassCollection classCollection);
    }

    public class AnimalAnalyzer extends Analyzer {
    private ClassNode identifiedClass = null;
    @Override
    public void run(ClassCollection classCollection) {
    for (ClassNode classNode : classCollection.getAllClassNodes()) {
    boolean isMatch = doesClassMatch(classNode); // method omitted from example
    if (isMatch) {
    identifiedClass = classNode;
    break;
    }
    }
    }
    }




    public interface Injector {
    void inject(List<Analyzer> analyzers);
    }

    public class AnimalInjector implements Injector {
    @Override
    public void inject(List<Analyzer> analyzers) {
    AnimalAnalyzer animalAnalyzer = null;
    for (Analyzer analyzer : analyzers) {
    if (analyzer instanceof AnimalAnalyzer) {
    animalAnalyzer = (AnimalAnalyzer) analyzer;
    }
    }
    if (animalAnalyzer == null) {
    throw new IllegalStateException("AnimalAnalyzer not found in list");
    }
    ... (bytecode generation and injection)
    }
    }


    One of the reasons that I chose to do it this way is that the analyzers have to be run in a specific order. For example, to identify a Dog which extends Animal, the latter has to be found first. For this purpose I created MasterAnalyzer, which stores a list of the analyzers in a specific order. When run is invoked on this analyzer, it calls run on the analyzers in the list in the right order.



    public class MasterAnalyzer extends Analyzer {
    private List<Analyzer> analyzers = new ArrayList<>();

    public MasterAnalyzer() {
    analyzers.add(new AnimalAnalyzer());
    analyzers.add(new DogAnalyzer());
    ... (more analyzers)
    }

    public List<Analyzer> getAnalyzers() {
    return analyzers;
    }

    @Override
    public void run(ClassCollection classCollection) {
    for (Analyzer analyzer : analyzers) {
    analyzer.run(classCollection);
    }
    }
    }


    The injectors, in turn, can all be run with the same command: inject(masterAnalyzers.getAnalyzers()). While this makes it easy at the client side, it causes the injectors to know more than they need to know. For instance, let's assume that we also have a CatAnalyzer. Now, when we run the DogInjector, the list of analyzers will include the CatAnalyzer, even though the DogInjector does not care about it. This, along with the nasty instanceof usages, causes red signals to me. Now I am reaching out to you more experienced developers for some tips on how to improve my design. While searching for alternative ways, I found the Visitor pattern, which could be applicable here. However, I am still unsure how to apply it and whether it would improve my design or not.










    share|improve this question







    New contributor




    Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.






















      up vote
      -1
      down vote

      favorite









      up vote
      -1
      down vote

      favorite











      I'm working on a Java reverse engineering project, where I am analyzing bytecode and trying to identify classes, methods and fields using the ASM framework. After identifying these I transform some classes to implement my custom interfaces with, e.g., getter methods.



      For identifying classes, I have created an abstract class Analyzer with an abstract method for running the analysis on a collection of classes. Child classes of Analyzer try to identify a certain class/field/method of interest. For instance, AnimalAnalyzer attempts to identify the class which represents an animal.



      After running the analyzers, I inject my own interfaces and their implementations into the classes. Similarly to Analyzer, I have created an Injector interface with an inject(List<Analyzer> analyzers) method. For each class that I want to inject there is a separate class which implements the interface, e.g., AnimalInjector. The injector iterates the list of Analyzers, which contain the results of their analysis, and uses the relevant ones by checking their type with the instanceof operator. By "relevant ones" I mean the analyzers which contain the information needed to generate the bytecode with.



      public abstract class Analyzer {    
      public abstract void run(ClassCollection classCollection);
      }

      public class AnimalAnalyzer extends Analyzer {
      private ClassNode identifiedClass = null;
      @Override
      public void run(ClassCollection classCollection) {
      for (ClassNode classNode : classCollection.getAllClassNodes()) {
      boolean isMatch = doesClassMatch(classNode); // method omitted from example
      if (isMatch) {
      identifiedClass = classNode;
      break;
      }
      }
      }
      }




      public interface Injector {
      void inject(List<Analyzer> analyzers);
      }

      public class AnimalInjector implements Injector {
      @Override
      public void inject(List<Analyzer> analyzers) {
      AnimalAnalyzer animalAnalyzer = null;
      for (Analyzer analyzer : analyzers) {
      if (analyzer instanceof AnimalAnalyzer) {
      animalAnalyzer = (AnimalAnalyzer) analyzer;
      }
      }
      if (animalAnalyzer == null) {
      throw new IllegalStateException("AnimalAnalyzer not found in list");
      }
      ... (bytecode generation and injection)
      }
      }


      One of the reasons that I chose to do it this way is that the analyzers have to be run in a specific order. For example, to identify a Dog which extends Animal, the latter has to be found first. For this purpose I created MasterAnalyzer, which stores a list of the analyzers in a specific order. When run is invoked on this analyzer, it calls run on the analyzers in the list in the right order.



      public class MasterAnalyzer extends Analyzer {
      private List<Analyzer> analyzers = new ArrayList<>();

      public MasterAnalyzer() {
      analyzers.add(new AnimalAnalyzer());
      analyzers.add(new DogAnalyzer());
      ... (more analyzers)
      }

      public List<Analyzer> getAnalyzers() {
      return analyzers;
      }

      @Override
      public void run(ClassCollection classCollection) {
      for (Analyzer analyzer : analyzers) {
      analyzer.run(classCollection);
      }
      }
      }


      The injectors, in turn, can all be run with the same command: inject(masterAnalyzers.getAnalyzers()). While this makes it easy at the client side, it causes the injectors to know more than they need to know. For instance, let's assume that we also have a CatAnalyzer. Now, when we run the DogInjector, the list of analyzers will include the CatAnalyzer, even though the DogInjector does not care about it. This, along with the nasty instanceof usages, causes red signals to me. Now I am reaching out to you more experienced developers for some tips on how to improve my design. While searching for alternative ways, I found the Visitor pattern, which could be applicable here. However, I am still unsure how to apply it and whether it would improve my design or not.










      share|improve this question







      New contributor




      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      I'm working on a Java reverse engineering project, where I am analyzing bytecode and trying to identify classes, methods and fields using the ASM framework. After identifying these I transform some classes to implement my custom interfaces with, e.g., getter methods.



      For identifying classes, I have created an abstract class Analyzer with an abstract method for running the analysis on a collection of classes. Child classes of Analyzer try to identify a certain class/field/method of interest. For instance, AnimalAnalyzer attempts to identify the class which represents an animal.



      After running the analyzers, I inject my own interfaces and their implementations into the classes. Similarly to Analyzer, I have created an Injector interface with an inject(List<Analyzer> analyzers) method. For each class that I want to inject there is a separate class which implements the interface, e.g., AnimalInjector. The injector iterates the list of Analyzers, which contain the results of their analysis, and uses the relevant ones by checking their type with the instanceof operator. By "relevant ones" I mean the analyzers which contain the information needed to generate the bytecode with.



      public abstract class Analyzer {    
      public abstract void run(ClassCollection classCollection);
      }

      public class AnimalAnalyzer extends Analyzer {
      private ClassNode identifiedClass = null;
      @Override
      public void run(ClassCollection classCollection) {
      for (ClassNode classNode : classCollection.getAllClassNodes()) {
      boolean isMatch = doesClassMatch(classNode); // method omitted from example
      if (isMatch) {
      identifiedClass = classNode;
      break;
      }
      }
      }
      }




      public interface Injector {
      void inject(List<Analyzer> analyzers);
      }

      public class AnimalInjector implements Injector {
      @Override
      public void inject(List<Analyzer> analyzers) {
      AnimalAnalyzer animalAnalyzer = null;
      for (Analyzer analyzer : analyzers) {
      if (analyzer instanceof AnimalAnalyzer) {
      animalAnalyzer = (AnimalAnalyzer) analyzer;
      }
      }
      if (animalAnalyzer == null) {
      throw new IllegalStateException("AnimalAnalyzer not found in list");
      }
      ... (bytecode generation and injection)
      }
      }


      One of the reasons that I chose to do it this way is that the analyzers have to be run in a specific order. For example, to identify a Dog which extends Animal, the latter has to be found first. For this purpose I created MasterAnalyzer, which stores a list of the analyzers in a specific order. When run is invoked on this analyzer, it calls run on the analyzers in the list in the right order.



      public class MasterAnalyzer extends Analyzer {
      private List<Analyzer> analyzers = new ArrayList<>();

      public MasterAnalyzer() {
      analyzers.add(new AnimalAnalyzer());
      analyzers.add(new DogAnalyzer());
      ... (more analyzers)
      }

      public List<Analyzer> getAnalyzers() {
      return analyzers;
      }

      @Override
      public void run(ClassCollection classCollection) {
      for (Analyzer analyzer : analyzers) {
      analyzer.run(classCollection);
      }
      }
      }


      The injectors, in turn, can all be run with the same command: inject(masterAnalyzers.getAnalyzers()). While this makes it easy at the client side, it causes the injectors to know more than they need to know. For instance, let's assume that we also have a CatAnalyzer. Now, when we run the DogInjector, the list of analyzers will include the CatAnalyzer, even though the DogInjector does not care about it. This, along with the nasty instanceof usages, causes red signals to me. Now I am reaching out to you more experienced developers for some tips on how to improve my design. While searching for alternative ways, I found the Visitor pattern, which could be applicable here. However, I am still unsure how to apply it and whether it would improve my design or not.







      java design-patterns polymorphism






      share|improve this question







      New contributor




      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question







      New contributor




      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question






      New contributor




      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked 4 hours ago









      Markus Kullberg

      1




      1




      New contributor




      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      Markus Kullberg is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });






          Markus Kullberg is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209867%2fpassing-a-list-of-base-class-objects-to-a-method-and-using-instanceof-to-filter%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes








          Markus Kullberg is a new contributor. Be nice, and check out our Code of Conduct.










          draft saved

          draft discarded


















          Markus Kullberg is a new contributor. Be nice, and check out our Code of Conduct.













          Markus Kullberg is a new contributor. Be nice, and check out our Code of Conduct.












          Markus Kullberg is a new contributor. Be nice, and check out our Code of Conduct.
















          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f209867%2fpassing-a-list-of-base-class-objects-to-a-method-and-using-instanceof-to-filter%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          Morgemoulin

          Scott Moir

          Souastre