Bridge

AKA: Handle/Body

In the presence of an abstraction of a set of classes and operations, such as when using an Abstract Factory to construct all the parts of your document, you can find many concrete versions of objects that share common features. Some of them do the same thing but with different concrete calls.

Perhaps your Abstract Factory allows you to choose the type of persistence layer you use. You select from simple file storage with JSON or a more complicated SQL-backed solution. If the objects produced by the factory are document elements, then each element may have a similar sequence of actions regardless of which concrete type they belong to.

The JSON-backed image object will:

  • Open the file store, reading the JSON as a queriable object,
  • Query it for the relevant data for the binary file path,
  • Then, pass the file path to an image loader.

The SQL-backed image object will:

  • Open a connection to the database,
  • Query it for the relevant data for the binary data location,
  • Then, pass the image data from a blob query into an image loader.

If we have a text section object, it will have some similar steps:

  • Open a connection to the database,
  • Query it for the relevant data for the text field,
  • Then, pass the formatting and content objects to the text builder.

Bridgeless

There can be many more abstractions and other possible storage solutions in a document. This becomes an N2 problem.

Instead of having the concrete objects do these steps, have a separate abstraction for the implementation details from the abstraction of the object using them.

The general abstract image object will:

  • Open a query object via the implementation abstraction interface
  • Query that object for the relevant data for the image loader call,
  • Then, pass the result to an image loader.

Bridged

So, we split the document element abstraction from parts of its implementation. We can use inheritance to refine new features and add new possibilities.

As another example, an ObjectInWorld can DrawSprite, but Character inheriting from ObjectInWorld will use DrawSprite many times to build up a representation. ObjectInWorld implements DrawSprite as m_render->DrawSprite, and m_render is an ObjectInWorldImp type.

Bridge allows platform or context-specific implementations of base class functions to be replaced by a variable to an object. The AbstractBase can extend its features, still calling into the primitive Implementation calls, allowing implementations to catch up when it’s worth it.

“We’re a designer-crafter team. The crafter is a carpenter; they work the wood. I’m the designer. I don’t work the wood, but I know how to direct the woodworker to create fabulous things.”