Bridge Pattern

This lesson discusses the decorator pattern in detail using a coding example.

What is the bridge pattern?

The bridge pattern allows separate components with separate interfaces to work together. It keeps an object’s interface separate from its implementation allowing the two to vary independently.

An example is of controlling an air conditioner with a remote. The air conditioners can be of different types, similarly, each of them is controlled by a different remote. The remotes can vary, that is, a new one with better features can be introduced but that won’t make any changes to the air conditioner classes. The same goes the other way around. Hence, the bridge pattern allows input and output devices to work together but vary independently.

Example #

Now let’s implement the air conditioners and remote controls example we discussed above.

class SimpleRemoteControl{
constructor(ac){
this.ac = ac;
this.on = function() {
this.ac.on();
};
this.off = function() {
this.ac.off();
};
this.setTemparature = function(temp) {
this.ac.setTemparature(temp);
};
}
};
class InvertorRemoteControl {
constructor(ac){
this.ac = ac;
this.heat = function() {
this.ac.heatOn();
};
this.cold= function() {
this.ac.coldOn();
};
this.on = function() {
this.ac.on();
};
this.off = function() {
this.ac.off();
};
this.setTemparature = function(temp) {
this.ac.setTemparature(temp);
};
}
};
class SimpleAC {
constructor(){
this.on = function() {
console.log('Simple AC is on');
};
this.off = function() {
console.log('Simple AC is off');
};
this.setTemparature = function(temp) {
console.log(`Simple AC's cooling is set to ` + temp + ' degrees');
};
}
}
class InvertorAC {
constructor(){
this.setting = "cool"
this.on = function() {
console.log('Invertor AC is on');
};
this.off = function() {
console.log('Invertor AC is off');
};
this.heatOn = function(){
this.setting = "heat"
console.log("Invertor AC's heating is on")
};
this.coldOn = function() {
this.setting = "cool"
console.log("Invertor AC's cooling is on")
};
this.setTemparature = function(temp) {
if(this.setting == "cool"){
console.log(`Invertor AC's cooling is set to ` + temp + ' degrees');
}
if(this.setting == "heat"){
console.log(`Invertor AC's heating is set to ` + temp + ' degrees');
}
};
}
}
const simpleAC = new SimpleAC()
const invertorAC = new InvertorAC()
const simpleRemote = new SimpleRemoteControl(simpleAC)
const invertorRemote = new InvertorRemoteControl(invertorAC)
simpleRemote.on()
simpleRemote.setTemparature(16)
simpleRemote.off()
invertorRemote.on()
invertorRemote.heat()
invertorRemote.setTemparature(22)
invertorRemote.off()

Explanation

The above example shows how to implement the bridge pattern to make air conditioners and remote controls work together. As discussed above, the input (remote control) and the output device (air conditioner) are separate components. So let’s start by looking at the air conditioner classes.

class SimpleAC {
  constructor(){
    this.on = function() {
        console.log('Simple AC is on');
    };

    this.off = function() {
        console.log('Simple AC is off');
    };

    this.setTemparature = function(temp) {
        console.log(`Simple AC's cooling is set to ` + temp + ' degrees');
    };
  }
}

SimpleAC is the commonly used AC, designed to provide only cooling. Its functionalities include switching on/off, and providing cooling at the temperature set.

class InvertorAC {
  constructor(){
   this.setting = "cool"
   //code...
    this.on = function() {
        console.log('Invertor AC is on');
    };

    this.off = function() {
        console.log('Invertor AC is off');
    };

    this.setTemparature = function(temp) {
      //code...
    };
  }
}

InvertorAC is similar to the SimpleAC since its functionalities also include switching on/off, and providing cooling at the temperature set. However, additionally, it can also offer heating depending on the setting chosen by the user. Let’s look at the additional code below:

class InvertorAC {
  constructor(){
   
   this.setting = "cool"
   
   //code...
 
   this.heatOn = function(){
     this.setting = "heat"
     console.log("Invertor AC's heating is on")
   };

   this.coldOn = function() {
     this.setting = "cool"
     console.log("Invertor AC's cooling is on")
   };
  
 
   this.setTemparature = function(temp) {
     if(this.setting == "cool"){
       console.log(`Invertor AC's cooling is set to ` + temp + ' degrees');
     }
     if(this.setting == "heat"){
       console.log(`Invertor AC's heating is set to ` + temp + ' degrees');
     }
        
   };
}

As you can see, it has heatOn and the coldOn methods to change the setting to heat or cool. The setTemparature method also shows the message depending on the setting.

Now let’s look at the remote control classes.

class SimpleRemoteControl{
  constructor(ac){
    this.ac = ac;

    this.on = function() {
        this.ac.on();
    };

    this.off = function() {
        this.ac.off();
    };

    this.setTemparature = function(temp) {
        this.ac.setTemparature(temp);
    };
  }
};

SimpleRemoteControl takes an ac object and allows operations such as: turning it on, off, and setting its temperature. We use it to control a SimpleAC.

Let’s look at the second type of remote control:

class InvertorRemoteControl {
  constructor(ac){
    this.ac = ac;
  

    this.heat = function() {
      this.ac.heatOn();
    };

    this.cold= function() {
      this.ac.coldOn();
    };

    this.on = function() {
        this.ac.on();
    };

    this.off = function() {
        this.ac.off();
    };

    this.setTemparature = function(temp) {
        this.ac.setTemparature(temp);
    };
  }
};

InvertorRemoteControl takes an ac object and allows operations such as: turning it on/off, turning on heat/cold mode, and setting its temperature. We use it to control an InvertorAC.

Note that even if the remote control class changes, it won’t affect the AC class. The two different classes can efficiently work together. You can pass the ac object to your remote control class, which will then perform the operations discussed on it.

//Example
const simpleAC = new SimpleAC()
const simpleRemote = new SimpleRemoteControl(simpleAC)
simpleRemote.on()
simpleRemote.setTemparature(16)
simpleRemote.off()

When to use the bridge pattern? #

You can use the bridge pattern:

  • if you want to extend a class in several independent dimensions

  • if you want to change the implementation at run time

  • if you want to share the implementation between objects


Now that you know what a bridge pattern is, it’s time to implement it!