lundi 27 avril 2020

Not able to distinguish injectable objects in the Bridge design pattern with Spring boot framework

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.

Aucun commentaire:

Enregistrer un commentaire