I am not sure how I can inject the abstract class and its extensions in the bridge design pattern in Spring. Let's consider the classic bridge design pattern example of shape:
Color.java
public interface Color {
String fill();
}
Blue.java
@Service("Blue")
public class Blue implements Color {
@Override
public String fill() {
return "Color is Blue";
}
}
Red.java
@Service("Red")
public class Red implements Color {
@Override
public String fill() {
return "Color is Red";
}
}
Shape.java
public abstract class Shape {
protected Color color;
@Autowired
private Something something;
@Value(${foo.bar})
private String fooBar;
public Shape(Color color){
this.color = color;
}
abstract public String draw();
}
Square.java
public class Square extends Shape {
public Square(Color color) {
super(color);
}
@Override
public String draw() {
return "Square drawn. " + color.fill();
}
}
Triangle.java
public class Triangle extends Shape {
public Triangle(Color color) {
super(color);
}
@Override
public String draw() {
return "Triangle drawn. " + color.fill();
}
}
BridgeApplication.java
@SpringBootApplication
public class BridgeApplication {
public static void main(String[] args) {
SpringApplication.run(BridgeApplication.class, args);
}
}
Controller:
@RestController
public class BridgeController {
@Autowired
@Qualifier("Red")
private Color red;
@GetMapping("/red")
@ResponseStatus(HttpStatus.OK)
public String redSquare() {
Shape square = new Square(red);
return square.draw();
}
}
The problem arises when we would like to inject the abstract class Shape or its extensions like Square or Triangle. Because of the fact that constructor accepts a Color object and we cannot decide if the Color is a type of Red or Blue (That's the whole point of using Bridge design pattern here) then we cannot define Shape or its extensions to be a Spring Bean because there will be multiple beans of the type Color available. The easy workaround is like what I did to construct the object directly instead of injecting it. However, now there will be all challenges regarding any value I am injecting or any other Bean I would like to inject in the Shape class or its extensions (like fooBar or something) because the corresponding classes are constructed manually.
One solution is to start dealing with the manual injection that will create a lot of unnecessary complexity with the value and bean injections and it's not a clean solution at all. Like this or referring to this question. So I was wondering if there is a clean way of having some form of Bridge design pattern in the Spring framework or due to the Spring limitations, there is none.