Bridge Design Pattern in Java

One of the structural patterns, the Bridge Pattern, decouples an abstraction from its implementation so that two can vary independently. The bridge uses encapsulation, aggregation and also it can use inheritance to separate responsibilities into different classes.

The Bridge Pattern can be thought of as two layers of abstraction. This pattern involves an interface which acts as a bridge which makes the functionality of concrete classes independent from interface implementer classes. Both types of classes can be altered structurally without affecting each other.

Decouple implementation from interface and hiding implementation details from client is the purpose of bridge design pattern.

The abstraction is an interface or abstract class and contains a reference to the implementer.
The refined abstraction is the child of the abstraction and takes finer details one level below. It hides the finer elements from implementers.
The implementer is likewise an interface or abstract class and higher level abstraction with basic operations.
Concrete implementers provide concrete implementation at run-time by implementing the above implementer.
Class Diagram

Bridge Pattern in Java
Implementation

The display of different formats of images on different operating systems is an example of the Bridge pattern. We might have different image abstractions for both jpg, png and gif images. The image structure is same across all operating systems, but how the image will be viewed is different on each Operating System(OS). This is the type of decoupling that the Bridge pattern allows. The following example demonstrates this pattern

First we have our below OS interface

package com.roytuts.designpattern.bridge;
public interface OS {
  void displayJPGImage();
  void displayPNGImage();
  void displayGIFImage();
}

Next we create two different implementations – one for Windows OS and another for Mac OS. These classes deal with specific implementations of displaying different images from each vendor.

package com.roytuts.designpattern.bridge;
public class WindowsOS implements OS {
  @Override
  public void displayJPGImage() {
    //WindowsOS specific implementation for displaying jpg image
    System.out.println("WindowsOS displays JPG image");
  }
  @Override
  public void displayPNGImage() {
    //WindowsOS specific implementation for displaying png image
    System.out.println("WindowsOS displays PNG image");
  }
  @Override
  public void displayGIFImage() {
    //WindowsOS specific implementation for displaying gif image
    System.out.println("WindowsOS displays GIF image");
  }
}
package com.roytuts.designpattern.bridge;
public class MacOS implements OS {
  @Override
  public void displayJPGImage() {
    //MacOS specific implementation for displaying jpg image
    System.out.println("MacOS displays JPG image");
  }
  @Override
  public void displayPNGImage() {
    //MacOS specific implementation for displaying png image
    System.out.println("MacOS displays PNG image");
  }
  @Override
  public void displayGIFImage() {
    //MacOS specific implementation for displaying gif image
    System.out.println("MacOS displays GIF image");
  }
}

Now we will create an abstraction for displaying image.

package com.roytuts.designpattern.bridge;
public abstract class OSImage {
  protected OS os;
  protected OSImage(OS os) {
    this.os = os;
  }
  public abstract void displayImage();
}

As the OSImage holds a reference to the OS, it can delegates the methods through to the interface. But what is we want a more specific functionality to contain these concepts:

package com.roytuts.designpattern.bridge;
public class ConcreteOS extends OSImage {
  public ConcreteOS(OS os) {
    super(os);
  }
  @Override
  public void displayImage() {
    os.displayJPGImage();
    os.displayPNGImage();
    os.displayGIFImage();
  }
}

Test the above pattern by creating the below test class

package com.roytuts.designpattern.bridge;
public class BridgePatternTest {
  /**
   * @param args
   */
  public static void main(String[] args) {
    OSImage windowsImage = new ConcreteOS(new WindowsOS());
    OSImage macImage = new ConcreteOS(new MacOS());
    windowsImage.displayImage();
    System.out.println();
    macImage.displayImage();
  }
}

Run the above class and see the below output.
Output

WindowsOS displays JPG image
WindowsOS displays PNG image
WindowsOS displays GIF image
MacOS displays JPG image
MacOS displays PNG image
MacOS displays GIF image

That’s all. Thank you for your reading.
 
 

Leave a Reply

Your email address will not be published. Required fields are marked *