Bridge Mode of Design Patterns

Keywords: Windows Linux

  • Functional Hierarchy of Classes
  • Class Implementation Level
  • Specific examples of bridging modes
  • Summary

Bridge means bridge. Its function is to connect two sides. The function of bridge mode is also the same. Bridge mode is connected by function level and implementation level of each class.

There are two words that may be a little strange, the functional level of the class and the implementation level of the class.

So let's introduce the two hierarchies first, because the bridge mode is to connect the two hierarchies.

Functional Hierarchy of Classes

For adding new functions, if there is a class now, we want to add a new function in this class without changing the original class, then we can inherit from this class by inheritance method, and then add a specific new method in the inherited class. This is the functional level of the class.

  • Parents have basic functions
  • Subclasses extend the functions of classes and add new functions

Note: The functional level of a class should not be too deep

Class Implementation Level

Used to add new implementations. If we now have an abstract class or interface, which defines the corresponding methods, but does not implement, for different specific implementations we need to inherit the abstract class or implementation interface, which is the implementation level of the class.

  • Parents define interfaces by declaring abstract methods
  • Subclasses implement interfaces by implementing specific methods

Hybridization and Separation of Class Hierarchy

So after learning the functional level and implementation level of a class, we can consider a question when we write subclasses, whether we want to add functions or implementations. When the class hierarchy has only one layer, the functional hierarchy and the implementation hierarchy are mixed together, which makes it easy for the class hierarchy to become complex and difficult to understand.
Therefore, we need to separate the functional and implementation levels of classes into two separate hierarchies, but we can not simply separate them. After separation, we need to add some connection. This connection is the bridge, which is the bridge mode we will talk about in this paper.

Concrete examples of bridge mode

The function of this example is to print and display something.

  • Let's first consider the functional hierarchy of classes.

The functional level of a class only needs to consider what specific needs to be considered, and the specific implementation is given to the implementation level to implement. In order to invoke the implementation level, the functional level needs to hold an object of the implementation level, that is, delegation.

Functional Level Base Class Display

package Bridge;

public class Display {
    private DisplatImpl impl;

    public Display(DisplatImpl impl) {
        this.impl = impl;
    }

    public void open() {
        impl.rawOpen();
    }

    public void print() {
        impl.rawPrint();
    }

    public void close() {
        impl.rawClose();
    }

    public final void display() {
        open();
        print();
        close();
    }
}

Then we add functionality to this class, which can be displayed many times.
COuntPlay:

package Bridge;

public class CountDisplay extends Display{

    public CountDisplay(DisplatImpl impl) {
        super(impl);
    }

    public void multiDisplay(int times) {
        open();
        for(int i=0;i<times;i++)
            print();
        close();
    }
}
  • Class Implementation Level

First, the base class of the implementation level of a class should be an interface or abstract class, which defines the method to be implemented.

package Bridge;

public abstract class DisplatImpl {
    public abstract void rawOpen();
    public abstract void rawPrint();
    public abstract void rawClose();
}

Then we look at a real implementation that implements the above interface.

public class StringDisplayImpl extends DisplayImpl {
    private String string;                              // String to display
    private int width;                                  // The width of a string calculated in byte units
    public StringDisplayImpl(String string) {           // The constructor receives the string to be displayed
        this.string = string;                           // Save it in a field
        this.width = string.getBytes().length;          // Save the width of the string in the field for use.
    }
    public void rawOpen() {
        printLine();
    }
    public void rawPrint() {
        System.out.println("|" + string + "|");         // Add "|" around and display
    }
    public void rawClose() {
        printLine();
    }
    private void printLine() {
        System.out.print("+");                          // Displays the "+" used to represent the corner of the box
        for (int i = 0; i < width; i++) {               // Display width "-"
            System.out.print("-");                      // Use it as the border of a box
        }
        System.out.println("+");                        // Displays the "+" used to represent the corner of the box
    }
}

Finally, we call these two levels:

public class Main {
    public static void main(String[] args) {
        Display d1 = new Display(new StringDisplayImpl("Hello, China."));
        Display d2 = new CountDisplay(new StringDisplayImpl("Hello, World."));
        CountDisplay d3 = new CountDisplay(new StringDisplayImpl("Hello, Universe."));
        d1.display();
        d2.display();
        d3.display();
        d3.multiDisplay(5);
    }
}

Operation results:


image.png

Class diagrams of the above examples:


image.png

The class diagram of the Bridge pattern is similar:


image.png

Summary

  • It's easier to expand after separation
    Bridging mode is characterized by separating the functional level of the class from the implementation level. The advantage of separation is that it is beneficial to extend them. When new functions are added, it is only necessary to add classes at the functional level. There is no need to make any changes to the implementation level of the class. And the added functionality can be used by all implementations.

For example, if we divide the OS-dependent parts of our program into max, windows and linux versions, we can use the implementation hierarchy in the class bridging hierarchy to represent those OS-dependent parts.

Posted by desmond_ckl on Thu, 13 Jun 2019 16:24:20 -0700