The Bridge Pattern

The Bridge Pattern

 

Earlier today I blogged about the Singleton Design Pattern and how the Common Language Runtime made our lives easier. For instance, through the deterministic initialization of static variables .Net negates much of the need for double-check locking mechanism typically used in the implementation of the Singleton Pattern. This got me to thinking about other patterns and their proper use as well as when it is best to use the different patterns at our disposal. The Gang of Four in the quintessential book Design Patterns Elements of Reusable Object Oriented Software explains:

 

A design pattern systematically names, motivates, and explains a general design that addresses a recurring design problem in object-oriented systems. It describes the problem, the solution, when to apply the solution, and its consequences. It also gives implementation hints and examples. The solution is a general arrangement of objects and classes that solve the problem. The solution is customized and implemented to solve the problem in a particular context.

 

The description is appropriate but for some reason it doesn’t quite do it for me. I know. I know. It’s a good statement and it correctly reflects what a pattern is supposed to do. However, I still prefer Christopher Alexander’s description:

 

Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice.

I don’t know why, but I really like that description so much better. It just lines it up on a tee and let’s you smack it out of the park. Specifically, when do we use a specific pattern? So now that we have defined why patterns are good, when do we use the Bridge Pattern? The Gang of Four, GoF and their book “Design Patterns Elements of Reusable Object Oriented Software” (for now on whenever I say GoF that is who I am referring to…after all this is a blog and you all know who I am talking about anyway) describe it as follows:

…decouples an abstraction from its implementation so that the two can vary independently.

At this point, I should probably get into the particulars of an implementation. I am not going to do this. What I wanted to talk about is “When” to use one pattern versus the other and “What” a pattern is trying to solve so that we have a better understanding of the “Why” we are using it in the first place. I can’t tell you how many times I have debated with others about using this pattern versus that pattern and so on. This is a fun debate and one none of us will ever completely get away from; however, too often we jump to the application of a pattern without giving much thought as to why the patterns are there in the first place. As Alexander says, they are there to “…describe the core of the solution to that problem,…”. THAT problem is why we are using patterns and THAT is what we should be talking about. Not the application or the implementation of the pattern. We can always get to that later. Once THAT is determined, the how becomes so much easier.

So when do we use the bridge patterns. I know. I know. When we want to separate the implementation from the…..blah blah blah…. We know this already. Real world examples always make life so much easier. Here is one (and provides guileless self-promotion).

Several years ago (year 2000) I wrote a pretty cool code generator called Template{X} that had a healthy repository of meta information you could capture about a project. I then provided a nice object layer to this Meta information and enabled you to interact with it via an ASP-like language and engine to generate code. In order to do this I had to provide database interaction with a repository that could change. I implemented the bridge pattern to do this. For example, I had the concept of a Table class and a TableImp implementation. For example my concrete implementation classes were COracleTableImp and CSqlTableImp, etc. The design looked something like this:

 

                        

 

This enabled me to “plug-into” my framework new implementations. But wait a minute. Didn’t I just do what I promised I wouldn’t? I discussed implementation. Yes. I did, after all we must at least provide a cursory overview of an implementation. But no more! I promise. But why use this pattern? What about the adapter pattern?

 

Versus the Adapter Pattern

The adapter pattern works well and the implementation isn’t too different from the bridge (but it is different). But again, we need to be discussing when to use the adapter versus the bridge. The adapter is great if you are adapting concrete functionality from one application to be used by another. In other words, I need to adapt Application A so that it looks like it is part of Application B. However, the Bridge pattern is better suited for designing a system where you expect to add additional functionality over time but you want your architecture to be flexible enough to handle the changes without becoming brittle. This brittleness often occurs as you attempt to add new functionality using traditional factoring and “Is-A” mentality. To quote another GoF’ism "encapsulate what varies" and "favor object composition over class inheritance".

 

Versus the Strategy Pattern

The pattern most closely aligned to the Bridge Pattern is the Strategy Pattern. Aside from any implementation differences, they vary in the decision to use one versus the other. Specifically, you use the strategy to

 

Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.

 

Wait a minute, this sounds a great deal like Bridge. What is this really saying? The reality is that they are very similar. However, you use the Strategy Pattern to encapsulate an algorithm or set of algorithms; whereas, you use the Bridge to separate and vary an abstraction from its implementation. If you are having troubles with this one. Don’t worry, like Chinese Water torture, it will eventually sink in ;)

 

Summary

I could go on and on and compare different patterns to the bridge pattern. However, at the end of the day we need to first define our problem before we come up with a solution. And since patterns are all about solutions to a problem, don't look at patterns until you have already defined the problem. Unless of course you merely want to see what patterns have to offer....but if you do this don't expect any answers.

 

-Mathew Nolton

 

No Comments