Category: Behavioral design patterns

Purpose: To decouple several mutually coupled objects to a single mediator object

1drv.ms/u/s! AquRvPz…

A typical scenario

In the UI interface, click a button, the state of this button will affect the state of other buttons, and change the display mode of the table, as shown below:

Scene effect:

  1. After clicking the left button, the table is left aligned and highlighted, while the center and right buttons are unhighlighted
  2. When the center button is clicked, the table is centered and the center button is highlighted. The left and right buttons are unhighlighted
  3. After clicking the right button, the table is aligned to the right and highlighted, while the left and center buttons are unhighlighted

Hard coded

It is easy to write the following code based on the above scenario

The three buttons and table object prototypes are as follows:

The left button

public class LeftButton {
    private MiddleButton middleButton;
    private RightButton rightButton;
    private Table table;  
      
    public LeftButton(MiddleButton middleButton, RightButton rightButton, Table table) {
        this.middleButton = middleButton;
        this.rightButton = rightButton;
        this.table = table;
    }

    public void click(a) {
        this.highlight();
        middleButton.cancelHighlight();
        rightButton.cancelHighlight();
        table.alignLeft();
    }

    public void highlight(a) {
        // Highlight self generated
    }
    public void cancelHighlight(a) {
        // Unhighlight}}Copy the code

Middle button and right button

public class MiddleButton {
    public MiddleButton(LeftButton leftButton, RightButton rightButton, Table table) {
        this.leftButton = leftButton;
        this.rightButton = rightButton;
        this.table = table;
    }
    // Logic is the same as LeftButton...
}

public class RightButton {
    public RightButton(LeftButton leftButton, RightButton middleButton, Table table) {
        this.leftButton = leftButton;
        this.middleButton = middleButton;
        this.table = table;
    }
    / / with LeftButton...
}
Copy the code

The table is as follows:

public class Table {
    public void alignLeft(a) {
        // Left-align content
    }

    public void alignMiddle(a) {
        // The content is centered
    }

    public void alignRight(a) {
        // Align content to the right}}Copy the code

You can see

  1. There is a tight coupling between the three buttons and a table object, and each button needs to hold references to the other buttons
  2. If a new button, such as the reset button, is added to the system, all the buttons and tables need to be adapted to this new button. Under the condition of variable number of components, the maintenance cost is huge (every new component and all components need to be adapted to it).

Pattern implementation

At this point, a new mediator object can be introduced to centrally handle the coupling code between these components. For example, SectionMediator’s interdependent buttons can be changed to only depend on the mediator. When the button’s self-generated state changes, the mediator can notify the mediator, and the mediator can handle the related behavior calls of the objects it affects.

Take LeftButton as an example to change the reference as follows:

public class LeftButton implements Component {
    private SectionMediator sectionMediator;

    public LeftButton(SectionMediator sectionMediator) {
        this.sectionMediator = sectionMediator;
    }

    public void click(a) {
        this.highlight();
        sectionMediator.changed(this);
    }
    // ...
}
Copy the code

You can see that the button only couples one mediator and notifies the mediator that the generated state has changed by calling sectionMediator.changed(this) when the generated state changes (click)

The mediator handles the update of the related object after the button is clicked, as follows:

public class SectionMediator implements Mediator {
    private LeftButton leftButton;
    private MiddleButton middleButton;
    private RightButton rightButton;
    private Table table;

    public SectionMediator(LeftButton leftButton, MiddleButton middleButton, RightButton rightButton, Table table) {
        this.leftButton = leftButton;
        this.middleButton = middleButton;
        this.rightButton = rightButton;
        this.table = table;
    }

    @Override
    public void changed(Component component) {
        if (component == leftButton) {
            middleButton.cancelHighlight();
            rightButton.cancelHighlight();
            table.alignLeft();
        } else if (component == middleButton) {
            leftButton.cancelHighlight();
            rightButton.cancelHighlight();
            table.alignMiddle();
        } else if(component == rightButton) { leftButton.cancelHighlight(); middleButton.cancelHighlight(); table.alignRight(); }}}Copy the code

You can see that in the CHANGED method, the subject of the state change is first judged, and then the affected object is called for the state change

UML

Why is the mediator model better

You can see that the mediator removes the direct coupling between objects, making the individual object structure clearer

A couple of points to note

A concrete implementation of the mediator pattern can be implemented using the observer pattern

The resources

  1. Xuliangzhan. Making. IO/vxe – table / #…
  2. www.geeksforgeeks.org/mediator-de…