The decorator pattern is well known and described.
See for example
https://en.wikipedia.org/wiki/Decorator_pattern
The question is how can we implement easily the pattern with
Spring.
Lets just do an example.
We have a SearchService which can be configuratively be switch on or off.
We have a simple interface
public interface SearchService{
List find(Param p);
}
and a simple implementation
@Component
public class DefaultSearchService implements SearchService{
public List find(Param p){
repository.find(p);
}
}
Our decorator logically implements the SearchService interface as well
@Component
public class SearchServiceDecorator implements SearchService{
private final SearchService searchService;
private final Config config;
@Autowired
public SearchServiceDecorator(SearchService searchService, Config config){
this.searchService = searchService;
}
public List find(Param p){
if(config.allowed())
searchSerice.find(p);
}
}
This will obviously not work. Spring cannot decide which version of SearchService to use.
The solution is quite elegant:
@Component
@Primary
public class SearchServiceDecorator implements SearchService{
private final SearchService searchService;
private final Config config;
@Autowired
public SearchServiceDecorator(@Named("defaultSearchService")SearchService searchService, Config config){
this.searchService = searchService;
}
public List find(Param p){
if(config.allowed())
searchSerice.find(p);
}
}
The @Primary annotation, according to its Javadoc "Indicates that a bean should be given preference when multiple candidates
* are qualified to autowire a single-valued dependency."
The @Named allows to inject the decorator chain.
Thats it :)