Bridge Pattern

The Bridge Pattern is used to separate the interface from its implementation so that both can vary independently (extension without subclassing). The normal inheritance of classes from an interface suffers from the following two limitations:

  • Extension could lead to an exponential number of subclasses.
  • Both the abstraction interface and its implementation are closely tied together

Unlike normal class B implements interface A and A has no idea of B; in Bridge pattern abstractions have a link to implementations. Abstraction knows about implementation.

bridge1.jpeg

Notes:

  • The instance of Implementation (impl) can either be in "Abstraction" interface or in its subclasses.
  • Subclasses of "Abstraction" can either be interface or concrete classes.
  • The two hierarchies are designed separately. Implementation interface doesn't have to correspond exactly to Abstraction's interface. Typically the Implementation interface provides only primitive operations, and Abstraction defines higher-level operations based on these primitives.
  • In situations where there's only one implementation, creating an abstract Implementor class isn't necessary. There is a one-to-one relationship between Abstraction and Implementor. Nevertheless, this separation is still useful when a change in the implementation of a class must not affect its existing clients—that is, they shouldn't have to be recompiled, just relinked.
  • When a client object invokes a method on the Abstraction object, it forwards the call to the Implementer object it contains. The Abstraction object may offer some amount of processing before forwarding the call to the Implementer object.

Related Patterns:

  • Abstract Factory can be used to choose the correct implementor for the abstraction hierarchy.
  • The Adapter Pattern makes unrelated classes work together. It is usually applied to systems after they're designed. Bridge, on the other hand, is used up-front in a design to let abstractions and implementations vary independently.

Example 1

bridge2.jpeg

Example 2

Imaging we want to write an application to read different file types (binary, text, etc) and write them to different streams (db, url, file, etc). We can create a Reader hierarchy with BinaryReader, TextReader, etc and each of them implement DbWriter, URLWriter, etc; all in one big tree. Another solution based on Bridge pattern is this:

public interface Reader {
    public String read();
}
 
public class TextReader implements Reader{
}
 
public class BinaryReader implements Reader {
}
 
public interface Writer {
    public void write();
}
 
public class FileWriter  implements Writer  {
 
    Reader reader;  // A pointer to the other hierarchy
 
    public FileWriter(Reader r) {
        reader = r;    
    }
 
    @Override
    public void write() {
        String out = reader.read();
        //now write it to file
    }
}
 
public class DbWriter implements Writer {
}
 
public class Client {
    public static void main(String[] args) {
        Reader reader = new TextReader();
        Writer writer = new FileWriter(reader);
        writer.write();
    }
}

Another good example (logging) can be found in: Software Architecture Design Patterns in Java, Partha Kuchana.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License