Java – Use services as “factories” to return different bean implementations

Use services as “factories” to return different bean implementations… here is a solution to the problem.

Use services as “factories” to return different bean implementations

I want to use this type of service class as a “factory” in my Spring application to return the correct implementation of DocumentProcessor in response to the provided enumeration value.

I

did this because I wanted to set up each processor itself as a component and take advantage of Autowiring instead of just creating new instances when each processor was needed.

I haven’t really seen this done anywhere else – can anyone tell me if this is a bad idea?

All TypeXYZDocumentProcessor classes are extensions of the abstract “DocumentProcessor” base class.

@Service
public class DocumentProcessorService {

@Autowired
  TypeXDocumentProcessor typeXDocumentProcessor;

@Autowired
  TypeYDocumentProcessor typeYDocumentProcessor;

@Autowired
  TypeZDocumentProcessor typeZDocumentProcessor;

public DocumentProcessor getDocumentProcessor(DocumentType docType) {
    switch (docType) {
      case TYPE_X:
        return typeXDocumentProcessor;
      case TYPE_Y:
        return typeYDocumentProcessor;
      case TYPE_Z:
        return typeZDocumentProcessor;
      default:
        return null;
    }
  }
}  

@Component
public class TypeXDocumentProcessor extends DocumentProcessor {
  ...
}

public abstract class DocumentProcessor {
  ...
}

Solution

This is my proposal, I used an interface instead of an abstract class, but if you really need an abstract class, you can return it.

@Service
public class DocumentProcessorService {

@Autowired
   you can add here for examlpe a @Qualifier("typeXDocumentProcessor"),
   then name your variable whatever you want.
  DocumentProcessor typeXDocumentProcessor;

@Autowired
  DocumentProcessor typeYDocumentProcessor;

@Autowired
  DocumentProcessor typeZDocumentProcessor;

public DocumentProcessor getDocumentProcessor(DocumentType docType) {
    switch (docType) {
      case TYPE_X:
        return typeXDocumentProcessor;
      case TYPE_Y:
        return typeYDocumentProcessor;
      case TYPE_Z:
        return typeZDocumentProcessor;
      default:
        return null;
    }
  }
}  

@Component
public class TypeXDocumentProcessor implements DocumentProcessor {
  ...
}
@Component
public class TypeYDocumentProcessor implements DocumentProcessor {
  ...
}
@Component
public class TypeZDocumentProcessor implements DocumentProcessor {
  ...
}

public interface class DocumentProcessor {
  ...
}

Related Problems and Solutions