Question

I had spend some time on this Bridge pattern example from wikipedia, however, i still do not understand what is this bridge pattern trying to explain.

interface DrawingAPI {
    public void drawCircle(double x, double y, double radius);
}

/** "ConcreteImplementor" 1/2 */
class DrawingAPI1 implements DrawingAPI {
   public void drawCircle(double x, double y, double radius) {
        System.out.printf("API1.circle at %f:%f radius %f\n", x, y, radius);
   }
}

/** "ConcreteImplementor" 2/2 */
class DrawingAPI2 implements DrawingAPI {
   public void drawCircle(double x, double y, double radius) {
        System.out.printf("API2.circle at %f:%f radius %f\n", x, y, radius);
   }
}

/** "Abstraction" */
interface Shape {
   public void draw();                                            // low-level
   public void resizeByPercentage(double pct);     // high-level
}

/** "Refined Abstraction" */
class CircleShape implements Shape {
   private double x, y, radius;
   private DrawingAPI drawingAPI;
   public CircleShape(double x, double y, double radius, DrawingAPI drawingAPI) {
       this.x = x;  this.y = y;  this.radius = radius;
       this.drawingAPI = drawingAPI;
   }

   // low-level i.e. Implementation specific
   public void draw() {
        drawingAPI.drawCircle(x, y, radius);
   }
   // high-level i.e. Abstraction specific
   public void resizeByPercentage(double pct) {
        radius *= pct;
   }
}

/** "Client" */
class Main {
   public static void main(String[] args) {
       Shape[] shapes = new Shape[2];
       shapes[0] = new CircleShape(1, 2, 3, new DrawingAPI1());
       shapes[1] = new CircleShape(5, 7, 11, new DrawingAPI2());

       for (Shape shape : shapes) {
           shape.resizeByPercentage(2.5);
           shape.draw();
       }
   }
}

The subclass CircleShape constructor takes 4 args, in its draw() method, the first 3 args are passed to the 4th arg which can be any subclass from DrawingAPI. So does this mean that using bridge pattern can increase flexibility? and are there more things this example can tell us?

Thanks!!!!

Was it helpful?

Solution

A more concrete example why this is useful will make it clearer. Suppose DrawingAPI1 encapsulates your graphics driver, while DrawingAPI2 does the same thing for your printer driver. Then DrawingAPI is the generic API for your graphics system. It lets you draw a CircleShape to your monitor and print it on a piece of paper using the same code, you only have to pass in the different DrawingAPI implementations. However, if you pass DrawingAPI into Shape.draw() instead of passing it into the constructor it would be more flexible because then you can use the same object graph for the monitor and the printer.

OTHER TIPS

The subclass CircleShape constructor takes 4 args, in its draw() method, the first 3 args are passed to the 4th arg which can be any subclass from DrawingAPI. So does this mean that using bridge pattern can increase flexibility? and are there more things this example can tell us?

It's not only the flexibility. The Bridge pattern decouples abstraction from implementation and both can vary differently.

Since CircleShape uses composition to contain DrawingAPI with-out inheritance, you can replace DrawingAPI API with any one of multiple implementations of DrawingAPI

Shape and CircleShape can change independently without dependency on DrawingAPI.

You can find more details about Bridge pattern in below SE post, which explains different example:

Does the Bridge Pattern decouples an abstraction from implementation?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top