The Bridge Pattern is commonly configured but often due to templates and generators rather than understanding the true intent. Since it is more of a design than code implementation, it can be easily missed. Nevertheless, it is one we often have available and should probably take advantage of more often.
The Bridge Pattern Defined
As always, we will start with the “Gang of Four” intent to set the stage for our discussion.
This is simple and easy to see in code. How often have you seen (for example) an interface and then a class that is the implementation of it? I have worked on numerous Spring applications that follow this pattern where I may have a customerDAO and then a customerDAOImpl. While this could be confused with a way to implement a C header file (*.h), that is not at all the goal. If our design stays static, then we may not need to take advantage of the bridge (the relationship of the DAO and DAOimpl classes). On the other hand, this makes extending that code much more manageable than pushing the two classes into one and using inheritance.
Applying The Pattern
The key to this pattern points to another common one we will cover another time, the MVC. The application of a bridge allows us to address classes in pieces instead of having to jam a poor implementation into a design (or vice versa). A good example is an interface and an implementation as noted above. When we want to inherit from the interface we can extend it without having to drag along the implementation; we can also extend the class without having to adjust the interface. Think of it as an extra layer of abstraction. From a data perspective, this is similar to implementing a many-to-many relationship. When we have multiple implementations to tie to some classes, then a bridge is needed.
Java, PHP, C#, etc.
This implementation is accomplished through an interface that is paired with a class that implements that interface. The extension can be accomplished from either of those two classes. That gives us the bridge. This does not vary much from language to language as interfaces are almost ubiquitous. As we have covered before, we typically can use the interface keyword to define an interface and class for the other side of the bridge. If there is an option to place implementation within the interface (rather than leaving it completely abstract), then that must be avoided in a bridge. Our goal is to push implementation as far down the relationship as possible. Thus making it easier to plug and play the pieces along the way.