Java programming language logo

Bridge Design Pattern

Bridge pattern separates an abstraction from its implementation, so that the two get loosely coupled and can vary independently.

In practice, the terms abstraction and implementation refer to objects. The abstraction object has a reference to the implementation object and delegates some responsibilities to it. Both of them can be implemented to their own interface, so their implementation can be changeable.

Bridge is a structural pattern.

Example

This Java example is about televisions and remote controls. There are several televisions and several remote controls. It is desirable to combine any remote to any television. This is possible because televisions and remote controls are programmed to interfaces.

Every remote control has a reference to a television and delegates responsibilities to it. For example, when the on button is pressed on a remote, it delegates the request to the television and that turns on.

As is was mentioned, televisions have a common interface.


package com.programcodex.designpatterns.bridge;

public interface Television {

    public void on();

    public void off();

    public void setChannel(int channel);

    public int getChannel();
}

The first television is the OldWoodenTV, which implements the Television interface. It's very simple.


package com.programcodex.designpatterns.bridge;

public class OldWoodenTV implements Television {

    private int channel; 
    
    @Override
    public void on() {
        System.out.println("Old wooden television is on");
    }

    @Override
    public void off() {
        System.out.println("Old wooden television is off");
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
        System.out.println("Channel: " + channel);
    }

    @Override
    public int getChannel() {
        return channel;
    }
}

The second and last television implementation in this example is the ColorTV, which is a much more modern television like the first one. This one has Bluetooth and can say farewell.


package com.programcodex.designpatterns.bridge;

public class ColorTV implements Television {

    private int channel; 
    
    @Override
    public void on() {
        System.out.println("Color television is on");
        connectToBluetoothSpeakers();
    }

    @Override
    public void off() {
        echoByeBye();
        System.out.println("Color television is off");
    }

    @Override
    public void setChannel(int channel) {
        this.channel = channel;
        System.out.println("Selected channel: " + channel);
    }

    @Override
    public int getChannel() {
        return channel;
    }
    
    private void connectToBluetoothSpeakers() {
        System.out.println("Connected to Bluetooth speakers");
    }

    private void echoByeBye() {
        System.out.println("Bye-bye");
    }
}

Now come the remote controls. Their interface is defined below.


package com.programcodex.designpatterns.bridge;

public interface RemoteControl {

    public void on();

    public void off();
    
    public void switchChannel(int channel);
    
    public void setPrevChannel();
    
    public void setNextChannel();
}

The UniversalRC class implements the RemoteControl interface. It holds a reference to a Television instance in a field and calls its methods. The Television type is an interface, so it can be OldWoodenTV or ColorTV.


package com.programcodex.designpatterns.bridge;

public class UniversalRC implements RemoteControl {

    private Television television;

    public UniversalRC(Television television) {
        this.television = television;
    }

    @Override
    public void on() {
        television.on();
    }

    @Override
    public void off() {
        television.off();
    }

    @Override
    public void switchChannel(int channel) {
        television.setChannel(channel);
    }

    @Override
    public void setPrevChannel() {
        television.setChannel(television.getChannel() - 1);
    }

    @Override
    public void setNextChannel() {
        television.setChannel(television.getChannel() + 1);
    }
}

The SimpleRC class is another implementation of the RemoteControl interface, and also has a Television instance reference, but it is a little bit simpler than the previous remote. It doesn’t support every operation of the interface, but it works.


package com.programcodex.designpatterns.bridge;

public class SimpleRC implements RemoteControl {

    private Television television;

    public SimpleRC(Television television) {
        this.television = television;
    }

    @Override
    public void on() {
        television.on();        
    }

    @Override
    public void off() {
        television.off();
    }

    @Override
    public void switchChannel(int channel) {
        television.setChannel(channel);
    }

    @Override
    public void setPrevChannel() {
        // not supported 
    }

    @Override
    public void setNextChannel() {
        // not supported
    }
}

And we are done. It’s time to run these things.

First, an OldWoodenTV and a ColorTV are instantiated. After that, they are used by the UniversalRC and the SimpleRC classes.

The testRemore method gets a remoteControl as a parameter. It presses the remote’s on button, switch channels and finally presses the off button.


package com.programcodex.designpatterns.bridge;

public class TestBridge {

    public static void main(String[] args) {
        Television owTv = new OldWoodenTV();
        Television colorTv = new ColorTV();

        System.out.println("Universal RC test:");
        
        RemoteControl rc = new UniversalRC(owTv);
        testRemore(rc);
        
        rc = new UniversalRC(colorTv);
        testRemore(rc);
        
        System.out.println("\nSimple RC test:");
        
        rc = new SimpleRC(owTv);
        testRemore(rc);
        
        rc = new SimpleRC(colorTv);
        testRemore(rc);
    }

    private static void testRemore(RemoteControl remoteControl) {
        System.out.println("");
        remoteControl.on();
        remoteControl.switchChannel(5);
        remoteControl.setNextChannel();
        remoteControl.setPrevChannel();
        remoteControl.off();
    }    
}

The output of the above test class:

The Bridge Design Pattern