📜 ⬆️ ⬇️

Bridge pattern extra touches

Discussion of the long-suffering pattern of the Bridge in Habré revealed many interesting opinions and delusions. Let's try to understand, reanimate this template in the eyes of those who struggle with the wording of the original GoF catalog, and show a few additional touches to those interested in the topic of templates.


Briefly about the patterns GoF (Gang of Four - "gang of four")



“We are not endowed with foresight, so those who attribute extraordinary abilities to the“ gang of four ”will be struck by the chaos of our development process.”
John Vlissides
')
“When we wrote our book, we really tried to hide something, We wanted to avoid talking about the fact that one template is a specialization of another, or one template is contained in another as its component. We did not want to be distracted, and decided to talk only about patterns. This is partly why we did not describe the “abstract class” as an independent template, since it is contained in most of the templates. I think it was a justified decision when creating the first template catalog, but now the situation has changed. People want to know about the relationships between the templates, and we need to tell them about it. ”
Ralph Johnson

“The design patterns developed by GoF take into account only aspects of the micro-architecture. It is necessary to choose the macroarchitecture correctly: splitting into levels, distribution, isolation of functions ..., and also nanoarchitecture: encapsulation, the principle of the Liska substitution (Barbara Liskov). It is possible that in some places it will be possible to use a certain design pattern, in any case, it is very unlikely that such a pattern has already been developed and described in any book. ”
Richard Helm

GoF templates are built on two basic principles.
  1. Find the points of change and encapsulate them.
  2. Composition of objects at run time is preferable to inheritance.
Criteria for including a template in a directory

Bridge Template ("Bridge")



Type: structural
Level: component
Another name: Handle / Body ("Description / Body")
Application time : the moment of design .

Purpose
The separation of a complex component into two independent, but interrelated hierarchical structures: functional abstraction and internal implementation.
This makes it easy to change any aspect of a component.

Demonstration

Consider the ideas underlying this pattern on the example of modeling a component called "Car". Practical value will not be an end in itself.
Step 1. The hierarchy of functionality (first level), in this case it will be integrated types of cars.


Step 2. The implementation space will reflect the options for representing the car in the depths of the manufacturer's company. Pay attention to the explosive increase in static links in the model and, accordingly, the number of classes to be developed when using inheritance. But at the time of execution, the complexity of the model is linear.




Step 3. Separation of hierarchies, postponing the binding until execution. Compare with the circuit element "multi-position switch" or "multiplexer".


Step 4. “Classic” presentation of the template with the specified features.


Comparison with inheritance

Functionality options: __ 2 ... ..3 .... 3 ... 4 ... ... 4 ... .5
Implementation options: ________ 2 ... ..2 ... .3 ... .3 ... ... 4 ... .4
Classes (inheritance): ______ 4 ... ..6 ... .9 ... 12 ... 16 ... 20
Classes (Bridge template): ______ 4 .... 5 ... .6 ... 7 ... ... 8 ... ..9

The architecture of the Bridge template allows the multiplexing of various variants of the external representation and internal implementation of the component. The term "multiplexing" means the possibility of association in any combination of external and internal elements, which provides an increase in the range of possible variations of the component.
Separating a component into two separate concepts, in addition, helps to facilitate understanding of the purpose of the component and its maintenance. This is explained by the fact that each branch of inheritance is built on the basis of one concept - either abstraction or implementation.

Important points


Borders: Functions and implementation are closely related hierarchies that are at the same conceptual level, reflecting the peculiarity of the structure of one component. Note that the implementation is in the “private / protected” part of the component and reflects the points of variation of the functional concept.
Example: GUI in Java. Public is in java.awt. *. Private in internal packages sun. *. This provides protection for an important invariant because there is no point in using, for example, a Win implementation on a Mac, and even less to allow an external (untrusted) code to replace the implementation.

Main hierarchy: The functional hierarchy is the main one, it knows about the variation and uses it (unidirectional association). The implementation hierarchy is subject to the needs of the required functions. That is why in GoF it turns out that the DrawRectangle () method is at the functional level, and DrawLine () at the platform implementations level.
With a bidirectional association, we are no longer getting a “bridge”, but a “go-between” for GoF.

Place among structural patterns: The classical wording speaks of the equivalence of changes in both hierarchies. However, one of the "bandits" John Vlissides is given the following list of points of variation.
ADAPTER - object interface;
BRIDGE - object implementation;
COMPOSITE - structure and composition of the object;
DECORATOR - the duties of the object without spawning a subclass;
FACADE - subsystem interface;
FLYWEIGHT - storage overhead;
PROXY - a way to access the object and / or its location.

Relationship with other templates: If you try to go to the “bridge” in the existing model, then in 99% of cases you either aggregate / adapt independent entities or use an intermediary / strategy to encapsulate the changes, just do not forget that the original template is a design time reception refactoring), such an initial step, but as soon as your “implementation” leaves the “private” zone and heals on its own it is no longer a “bridge”. The connection between levels, dependency inversion, anything but a “bridge” in the sense of GoF.
The “bridge” must be “configured” at the time of execution, do not forget any combination of Abstraction - Realization is possible. The logic of “configuring” and observing invariants is either hidden in the component or given to a higher level component (in difficult cases there may be an Abstract factory, a dependency container, etc.).
Such options as the separation of the implementation between objects at the time of execution, the use of multiple implementations at the same time. They are described in GoF and can be considered as exotic cases in which the “bridge” context for the application of another pattern.

Define for your component: what the concept of equality of entities in relation to the Bridge pattern means. Is it necessary to compare only abstractions or only realizations of objects, or do we need to consider them as a whole?

The problem of the quality of the model: is that often the development of the implementation of the template is carried out on the basis of one or two possible variations. The danger is that with the subsequent development of the pattern, it turns out that some of the elements that were considered basic, in fact, are concrete variations based on abstraction and / or implementation. This moment was somewhat messy in the article of the user tac link . But it is important to remember that templates do not determine the quality of the domain model, the depth and adequacy of the model essentially depends on the primary tasks of the application, the designer’s qualifications and the opinion of experts in the relevant field.
Empirical (mechanical) criterion - if here and now (at the time of design) you really need (Functionality options + Implementation options)> 6, i.e., the ratio of the level is 3: 3, 3: 4 and higher, then
- break hierarchies
- What is the ratio of code volume turned out to be 80%: 20%, 50%: 50%, 20% -80%?
- think whether your original concept has broken up into independent entities?

The problem of the original metaphor: construction metaphor + vague wording in the catalog leads to the fact that any horizontal arrow between two independent hierarchies is declared a "bridge". Metaphor "multiplexer" better reflects the basic technique of implementation, and limiting the level of one component holds a clear logical border with other patterns.
I hope the “extra touches” outlined made it possible to more clearly show the essence of the template.

Bibliography

E. Gamma, R. Helm, R. Johnson, D. Vlissides - Object-Oriented Design Techniques. Design patterns. Catalog templates GoF.
J. Vlissides - Applying design patterns. Additional touches. Here are the templates that are not included in the main directory Pull / Push, Multicast ... and just interesting sketches of creative torment "gangs".
A. Shalloway, J. Trott - Design Patterns. A new approach to object-oriented analysis and design. Reasoning about the vagueness of the formulation of the "bridge" and the search for the context of application. Also good reasoning is about combining / applying patterns.
S.Stelting, O. Maassen - Application of JAVA templates. Clear positioning of the “bridge” as a component level template. Introducing the telephone switch metaphor.

Source: https://habr.com/ru/post/138902/


All Articles