Applying the Service Locator Pattern to Decouple File Parsers in Spring
This article demonstrates how to replace tightly‑coupled if‑else or switch‑case parser selection with the Service Locator Pattern in a Spring Java application, enabling easy addition of new file‑type parsers without modifying client code and adhering to the open‑closed principle.
In many Java projects developers select a parser implementation with if else or switch case statements based on the file type, which creates a tight coupling between the client and concrete parsers.
The Service Locator Pattern can break this coupling by providing a central locator that returns the appropriate Parser implementation for a given ContentType , allowing new parsers to be added without changing the client.
File Parser Example
First, define an enum for the supported content types.
public enum ContentType {
JSON,
CSV
}Define a common parser interface.
public interface Parser {
List parse(Reader r);
}Implement concrete parsers for each type.
// CSV parser
@Component
public class CSVParser implements Parser {
@Override
public List parse(Reader r) { /* ... */ }
}
// JSON parser
@Component
public class JSONParser implements Parser {
@Override
public List parse(Reader r) { /* ... */ }
}A naïve client would use a switch statement.
@Service
public class Client {
private Parser csvParser, jsonParser;
@Autowired
public Client(Parser csvParser, Parser jsonParser) {
this.csvParser = csvParser;
this.jsonParser = jsonParser;
}
public List getAll(ContentType contentType) {
switch (contentType) {
case CSV: return csvParser.parse(reader);
case JSON: return jsonParser.parse(reader);
// ...
}
return null;
}
}When a new XML type is required, the client must be modified, violating the open‑closed principle.
Applying the Service Locator Pattern
Define a locator interface that returns a parser based on the content type.
public interface ParserFactory {
Parser getParser(ContentType contentType);
}Configure Spring to create a ServiceLocatorFactoryBean for this interface.
@Configuration
public class ParserConfig {
@Bean("parserFactory")
public FactoryBean serviceLocatorFactoryBean() {
ServiceLocatorFactoryBean factoryBean = new ServiceLocatorFactoryBean();
// set the service‑locator interface
factoryBean.setServiceLocatorInterface(ParserFactory.class);
return factoryBean;
}
}Register each parser bean with a name that matches the enum constant.
// CSV parser bean
@Component("CSV")
public class CSVParser implements Parser { /* ... */ }
// JSON parser bean
@Component("JSON")
public class JSONParser implements Parser { /* ... */ }
// XML parser bean
@Component("XML")
public class XMLParser implements Parser { /* ... */ }Extend the enum to include the new type.
public enum ContentType {
JSON,
CSV,
XML
}The client now only needs the factory; no switch statement is required.
@Service
public class Client {
private ParserFactory parserFactory;
@Autowired
public Client(ParserFactory parserFactory) {
this.parserFactory = parserFactory;
}
public List getAll(ContentType contentType) {
// Directly obtain the appropriate parser
return parserFactory.getParser(contentType).parse(reader);
}
}With this setup, adding a new parser (e.g., for XML) only requires creating the parser class and a bean name; the client remains untouched, satisfying the open‑closed principle.
In‑Depth Analysis of the Service Locator Pattern
The pattern removes the client’s direct dependency on concrete implementations. As Martin Fowler describes, a service locator is an object that knows how to obtain any service the application may need, returning the appropriate service on demand.
Spring’s ServiceLocatorFactoryBean implements the FactoryBean interface to produce a service‑factory bean that can locate services by name.
Conclusion
Using the Service Locator Pattern provides a clean way to extend Spring’s inversion‑of‑control container for scenarios where dependency injection alone is not sufficient, while still keeping dependency injection as the preferred approach.
Final Note
If you found this tutorial helpful, please like, share, and follow the author for more technical content.
Code Ape Tech Column
Former Ant Group P8 engineer, pure technologist, sharing full‑stack Java, job interview and career advice through a column. Site: java-family.cn
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.