This chapter is from the book

This chapter is from the book

Bridge

The Bridge pattern focuses on the implementation of an
abstraction. Design Patterns (Gamma et al. 1995) uses the word
abstraction to refer to a class that relies on a set of abstract
operations, where several implementations of the set of abstract operations are
possible.

The ordinary way to implement an abstraction is to create a class hierarchy,
with an abstract class at the top that defines the abstract operations; each
subclass in the hierarchy provides a different implementation of the set of
abstract operations. This approach becomes insufficient when you need to
subclass the hierarchy for another reason. It can also happen that the abstract
operations need to be defined and implemented in advance of abstractions that
will use them.

You can create a bridge by moving the set of abstract operations to an
interface, so that an abstraction will depend on an implementation of the
interface. The intent of the Bridge pattern is to decouple an abstraction from
the implementation of its abstract operations, so that the abstraction and its
implementation can vary independently.

A Classic Example of Bridge: Drivers

A common use of Bridge occurs when an application uses a driver. A driver is
an object that operates a computer system or an external device according to a
well-specified interface. Applications that use drivers are abstractions:
The effect of running the application depends on which driver is in place. Each
driver is an instance of the Adapter pattern, providing the interface a client
expects, using the services of a class with a different interface. An overall
design that uses drivers is an instance of Bridge. The design separates
application development from the development of the drivers that implement the
abstract operations on which the applications rely.

An everyday example of applications using drivers to operate computer systems
appears in database access. Database connectivity in Java usually depends on
JDBC. ("JDBC" is a trademarked name, not an acronym.) A good resource
that explains how to apply JDBC is JDBC Database Access with Java™
(Hamilton, Cattell, and Fisher 1997). In short, JDBC is an application
programming interface (API) for executing structured query language (SQL)
statements. Classes that implement the interface are JDBC drivers, and
applications that rely on these drivers are abstractions that can work with any
database for which a JDBC driver exists. The JDBC architecture decouples an
abstraction from its implementation so that the two can vary
independentlyan excellent example of Bridge.

To use a JDBC driver, you load it, connect to a database, and create a
Statement object:

A discussion of how the DriverManager class works is outside the scope of a
discussion on Bridge. The point here is that the variable s is a Statement
object, capable of issuing SQL queries that return result sets:

Figure 6.1 shows a UML sequence diagram that illustrates the message flow in
a typical JDBC application. Fill in the missing type names and the missing
message name in this illustration.

A solution appears on page 371.

Figure 6.1 is a sequence diagram. You can use a class diagram to show the
relationship of the application to the driver it applies. Figure 6.2 shows the
general form of an abstraction and its implementation in an application of the
Bridge pattern. This figure brings out the separation of an abstraction and its
implementation. The effect of calling the operation() method depends on which
implementation of the Implementor interface is in place.

Figure 6.1: This diagram shows most of the typical message flow in a JDBC
application.

Figure 6.2: A Bridge structure moves the abstract operations that an abstraction relies on into a separate interface.

It can be challenging to see how the classes in a JDBC application align with
the Bridge structure that Figure 6.2 shows. The questions to answer are: Which
classes are abstractions? Which classes are "implementations"?

Consider the _JDBCAdapter class that Sun Microsystems packages in the JDK as
a demonstration of how to display data from a database table. This class
implements the TableModel interface as shown in Figure 6.3.

The JDBCAdapter class constructor establishes a database connection and
creates a Statement object. The adapter passes queries to the Statement object
and makes the results available in a GUI component.

The JDBCAdapter class assumes that a client will call executeQuery() before
making calls to extract data from the query. The results of not providing a
query are somewhat unpredictable. Noticing this, suppose that you decide to
subclass JDBCAdapter with an OzJDBCAdapter class that throws a NoQuery
exception if a client forgets to issue a query before asking for data.

Challenge 6.2

Draw a diagram that shows the relationships among the classes _JDBCAdapter,
OzJDBCAdapter, NoQuery, and Statement.

A solution appears on page 371.

The JDBC architecture clearly divides the roles of the driver writer and the
application writer. In some cases, this division will not exist in advance, even
if you are using drivers. You may be able to set up drivers as subclasses of an
abstract superclass, with each subclass driving a different subsystem. In such a
case, you can be forced to set up a Bridge when you need more flexibility.