Bridge is a struc­tur­al design pat­tern that lets you split a large class or a set of close­ly relat­ed class­es into two sep­a­rate hier­ar­chies—abstrac­tion and imple­men­ta­tion—which can be devel­oped inde­pen­dent­ly of each other.

Problem: many design decisions are made final at design time or at compile time

Solution: the bridge pattern allows to delay the binding between an interface and its subclass to the startup time of the system

image.png

image.png

image.png

Abstrac­tion (also called inter­face) is a high-level con­trol layer for some enti­ty. This layer isn’t sup­posed to do any real work on its own. It should del­e­gate the work to the imple­men­ta­tion layer (also called plat­form).

When talk­ing about real appli­ca­tions, the abstrac­tion can be rep­re­sent­ed by a graph­i­cal user inter­face (GUI), and the imple­men­ta­tion could be the under­ly­ing oper­at­ing sys­tem code (API) which the GUI layer calls in response to user interactions.

Mak­ing even a sim­ple change to a mono­lith­ic code­base is pret­ty hard because you must under­stand the entire thing very well. Mak­ing changes to small­er, well-defined mod­ules is much easier.

Mak­ing even a sim­ple change to a mono­lith­ic code­base is pret­ty hard because you must under­stand the entire thing very well. Mak­ing changes to small­er, well-defined mod­ules is much easier.

Structure

image.png

  1. The Abstrac­tion pro­vides high-level con­trol logic. It relies on the imple­men­ta­tion object to do the actu­al low-level work.
  2. The Imple­men­ta­tion declares the inter­face that’s com­mon for all con­crete imple­men­ta­tions. An abstrac­tion can only com­mu­ni­cate with an imple­men­ta­tion object via meth­ods that are declared here. The abstrac­tion may list the same meth­ods as the imple­men­ta­tion, but usu­al­ly the abstrac­tion declares some com­plex behav­iors that rely on a wide vari­ety of prim­i­tive oper­a­tions declared by the imple­men­ta­tion.
  3. Con­crete Imple­men­ta­tions con­tain plat­form-spe­cif­ic code.
  4. Refined Abstrac­tions pro­vide vari­ants of con­trol logic. Like their par­ent, they work with dif­fer­ent imple­men­ta­tions via the gen­er­al imple­men­ta­tion interface.
  5. Usu­al­ly, the Client is only inter­est­ed in work­ing with the abstrac­tion. How­ev­er, it’s the client’s job to link the abstrac­tion object with one of the imple­men­ta­tion objects.

<aside>

Applicability

<aside>

How to Implement

  1. Iden­ti­fy the orthog­o­nal dimen­sions in your class­es. These inde­pen­dent con­cepts could be: abstrac­tion/plat­form, domain/infra­struc­ture, front-end/back-end, or inter­face/imple­men­ta­tion.
  2. See what oper­a­tions the client needs and define them in the base abstrac­tion class.
  3. Deter­mine the oper­a­tions avail­able on all plat­forms. Declare the ones that the abstrac­tion needs in the gen­er­al imple­men­ta­tion interface.
  4. For all plat­forms in your domain cre­ate con­crete imple­men­ta­tion class­es, but make sure they all fol­low the imple­men­ta­tion interface.
  5. Inside the abstrac­tion class, add a ref­er­ence field for the imple­men­ta­tion type. The abstrac­tion del­e­gates most of the work to the imple­men­ta­tion object that’s ref­er­enced in that field.
  6. If you have sev­er­al vari­ants of high-level logic, cre­ate refined abstrac­tions for each vari­ant by extend­ing the base abstrac­tion class.
  7. The client code should pass an imple­men­ta­tion object to the abstrac­tion’s con­struc­tor to as­so­ciate one with the other. After that, the client can for­get about the imple­men­ta­tion and work only with the abstrac­tion object.” </aside>