简体   繁体   中英

“Inject” interface implementions into a class in java

I'm wrting something that look like this (of course its a bit more complex than this sample):

public class DoOnAll {

    private List<IActionPerformer> actionPerformers;

    public DoOnAll(List<IActionPerformer> actionPerformers) {
        this.actionPerformers = actionPerformers;
    }

    public void callFromSomeWhere(String path) {
        File f = new File(path);
        List<File> list = Arrays.asList(f.listFiles());
        for (File file : list) {
            for (IActionPerformer action : actionPerformers) {
                action.perform(file);
               }
        }
    }

}

public interface IActionPerformer {
    public void perform(File file);
}

public class SomePerformer implements IActionPerformer {

    public void perform(File file) {
        if (getFileType(file) = ".txt") {
            doSomething
        }
    }
}

I have 2 questions:

  1. Should I move the condition in SomePerformer to another method, boolean accept(File file) for example, and also add this method declartion to the interface? If so, how would I "collect" all the accepted classes in DoOnAll ? just go through the actionPerformers list and add all the accepeted to another list and then go through the list of accepted and .perform on them? Or is there another way usually used in the methodology?

  2. Which ways are there for injecting the actionPerformrs list into the class? I want to write independent implementations and define in a file, say xml file, which ones to inject into the list.

In answer to your second question, you should look into dependency injection . Java has a few good frameworks that can do this for you, for example:

Spring in particular allows you to define your application's components and dependencies in XML files. For examples see:

This last link has a subsection on constructor injection: creating java objects with dependencies supplied to their constructors, as your class DoOnAll requires.

WRT question 2: I agree with Dan, Spring or Guice.

WRT question 1: IMHO I would not create a conditional method as part of the interface. Either way you must call one method on each object, why call two? Let the object determine for itself if processing should be done. This also prevents any potential overhead in invoking multiple methods on the class. It also makes the calling method more straightforward.

Question 1. What you described is a chain-of-responsibility pattern. You can also check if a Performer can execute on file, of no - use next performer from a list. If no performes left - exception. You can use another method or make your perform method return true/false of throw exception if it can't perform.

Question 2. Use Spring in a simplest manner. Do it like:

ApplicationContext context = new ClassPathXmlApplicationContext("some_configuration.xml");

You can also try Google Guice.

General suggestions here:

  1. Start simple (with what you have), and extend your interface when you have a use (case) for it. I'd just do if (accept(someFile)) perform(someFile); in an AbstractPerformer.performIfAccepted(File) method.

  2. See other answers, I'm no expert in this area.

1) First off keep it simple... I think you need to decide what it is you want to do. Is it to (a) give a first responder the chance to respond to the presence of a file of a certain type, (b) allow all possible responders for that type to respond or (c) to identify a single specific responder to a file type.

If:

a) See Peter Gwiazda's answer (IMO).

b) Similar to (a) but permit multiple responders in the chain.

c) Where there is always a specific responder to a file type, you could use a factory to obtain a specific instance based on the file type. This hides the specifics of the implementation. There are disadvantages in an IoC environment but the factory can still be populated using IoC if required.

2) Check out "Inversion of Control" metaphor in general and Spring in particular (as already suggested).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM