Appearance mode of design mode

Time:2022-6-20

Appearance mode, also known as facade mode, belongs to structural mode; It is a mode that makes multiple complex subsystems more accessible by providing a consistent interface. This mode has a unified interface to the outside, and the external application does not need to care about the specific details of the internal subsystem, which will greatly reduce the complexity of the application and improve the maintainability of the program.

Now microservices and modularity are becoming more and more popular. We will divide a complex system into several smaller subsystems. But after doing so, the function of the system will become stronger and stronger, the number of subsystems will become more and more, and the access of customers to the system will become more and more complex. At this time, if the internal system changes, the client will also change, which violates the “opening and closing principle” and the “Demeter’s law”. Therefore, it is necessary to provide a unified interface for multiple subsystems to reduce the coupling of the system. This is the goal of the appearance mode.

The purpose of the appearance pattern is to provide a centralized and simplified communication channel for the subsystem, rather than adding new behaviors to the subsystem. If a appearance mode cannot provide all the behaviors of the subsystem to the outside world, the facade class or its subclasses can provide the behaviors of the subsystem to the outside world by modifying the facade class or inheriting the facade class. However, if a subsystem does not have a certain behavior, it is wrong to provide this new behavior by modifying or inheriting the facade class.

Do not use appearance mode

A security system consists of two video recorders, three electric lights, a remote sensor and an alarm. The operators of the security system need to start and shut down these instruments frequently. First, the operator who operates the security system must directly operate all these components without using the facade mode.

UML class diagrams not applicable to appearance patterns are as follows:

As shown above, the client object needs to refer to all camera, light, sensor and alarm objects. The client object must know everything about the security system. If the system introduces a new object, there will be a lot to modify.

video recorder:

package com.charon.facade;

/**
 * @className: Camera
 *@description: video recorder system
 * @author: charon
 * @create: 2022-03-22 22:27
 */
public class Camera {

    /**
     *Turn on the VCR
     */
    public void turnOn(){
        System. out. Println ("video recorder on...");
    }

    /**
     *Turn off the video recorder
     */
    public void turnOff(){
        System. out. Println ("VCR off...");
    }

    /**
     *Rotary video recorder
     */
    public void rotate(int degress){
        System. out. Println ("VCR rotation" + degree + "degree");
    }
}

electric light:

package com.charon.facade;

/**
 * @className: Light
 *@description: bulb
 * @author: charon
 * @create: 2022-03-22 22:30
 */
public class Light {

    /**
     *Turn on the bulb
     */
    public void turnOn(){
        System. out. Println ("bulb on...");
    }

    /**
     *Turn off the bulb
     */
    public void turnOff(){
        System. out. Println ("light bulb off...");
    }

    /**
     *Change bulb
     */
    public void changBulb(){
        System. out. Println ("changed a bulb");
    }
}

a sensor:

package com.charon.facade;

/**
 * @className: Sensor
 *@description: sensor
 * @author: charon
 * @create: 2022-03-22 22:31
 */
public class Sensor {

    /**
     *Turn on the sensor
     */
    public void activate(){
        System. out. Println ("sensor on...");
    }

    /**
     *Turn off the sensor
     */
    public void deactivate(){
        System. out. Println ("sensor off...");
    }

    /**
     *Trigger sensor
     */
    public void trigger(){
        System. out. Println ("sensor triggered...);
    }
}

Alarm:

package com.charon.facade;

/**
 * @className: Alarm
 *@description: alarm
 * @author: charon
 * @create: 2022-03-22 22:33
 */
public class Alarm {
    /**
     *Turn on the alarm
     */
    public void activate(){
        System. out. Println ("alarm on...");
    }

    /**
     *Turn off the alarm
     */
    public void deactivate(){
        System. out. Println ("alarm off...");
    }

    /**
     *Sound the alarm
     */
    public void ring(){
        System. out. Println ("the alarm is sounded...);
    }

    /**
     *Stop the alarm
     */
    public void stopRing(){
        System. out. Println ("the alarm is turned off...);
    }
}

Test:

package com.charon.facade;

/**
 * @className: Client
 *@description: appearance mode
 * @author: charon
 * @create: 2022-03-21 22:30
 */
public class Client {

    private static Camera camera1 = new Camera(), camera2 = new Camera();

    private static Light light1 = new Light(), light2 = new Light(), light3 = new Light();

    private static Sensor sensor = new Sensor();

    private static Alarm alarm = new Alarm();

    public static void main(String[] args) {
        camera1.turnOn();
        camera2.turnOn();
        light1.turnOn();
        light2.turnOn();
        light3.turnOn();
        sensor.activate();
        alarm.activate();

        light1.changBulb();
        camera1.rotate(180);
        sensor.trigger();
        alarm.ring();
    }
}

Print:
    The video recorder is turned on....
    The video recorder is turned on....
    The light bulb is on....
    The light bulb is on....
    The light bulb is on....
    The sensor is on....
    The alarm is on....
    Changed a light bulb
    The video recorder rotates 180 degrees
    The sensor is triggered...
    The alarm went off...

Use appearance mode

The UML class diagram using the appearance pattern is as follows:

In appearance mode, only facade role and subsystem role are involved:

  • Facade role: the client can call the methods of this role. This role knows the functions and responsibilities of the relevant (one or more) subsystems. Under normal circumstances, this role will delegate all requests sent from the client to the corresponding subsystems.
  • Subsystem role: there can be one or more subsystems at the same time. Each subsystem is not a single class, but a collection of classes. Each subsystem can be called directly by the client or by the facade role. The subsystem does not know the existence of the facade. For the subsystem, the facade is just another client.

Facade:

package com.charon.facade;

/**
 * @className: SecurityFacade
 *@description: facade role
 * @author: charon
 * @create: 2022-03-22 23:02
 */
public class SecurityFacade {

    private static Camera camera1 = new Camera(), camera2 = new Camera();

    private static Light light1 = new Light(), light2 = new Light(), light3 = new Light();

    private static Sensor sensor = new Sensor();

    private static Alarm alarm = new Alarm();

    /**
     *System startup
     */
    public void activate(){
        camera1.turnOn();
        camera2.turnOn();
        light1.turnOn();
        light2.turnOn();
        light3.turnOn();
        sensor.activate();
        alarm.activate();
    }

    /**
     *System shutdown
     */
    public void deactivate(){
        camera1.turnOff();
        camera2.turnOff();
        light1.turnOff();
        light2.turnOff();
        light3.turnOff();
        sensor.deactivate();
        alarm.deactivate();
    }
}

Test:

package com.charon.facade;

/**
 * @className: Client
 *@description: appearance mode: http://c.biancheng.net/view/1369.html
 * @author: charon
 * @create: 2022-03-21 22:30
 */
public class Client {

    private static SecurityFacade facade = new SecurityFacade();

    public static void main(String[] args) {
        facade.activate();
        facade.deactivate();
    }
}

Print:
    The video recorder is turned on....
    The video recorder is turned on....
    The light bulb is on....
    The light bulb is on....
    The light bulb is on....
    The sensor is on....
    The alarm is on....
    The VCR is off....
    The VCR is off....
    Turn off the light bulb....
    Turn off the light bulb....
    Turn off the light bulb....
    The sensor is off....
    The alarm is off....

The facade pattern is a typical application of the “Demeter’s law”, which has the following main advantages:

  1. The coupling between the subsystem and the client is reduced, so that the change of the subsystem will not affect the client class that calls it.
  2. It shields subsystem components from customers, reduces the number of objects handled by customers, and makes the subsystem easier to use.
  3. It reduces the compilation dependency in large software systems and simplifies the migration process between different platforms, because compiling one subsystem will not affect other subsystems or appearance objects.

The main disadvantages of facade mode are as follows:

  1. It can not well restrict the use of subsystem classes by customers, and it is easy to bring unknown risks.
  2. Adding a new subsystem may require modifying the appearance class or the source code of the client, which violates the “opening and closing principle”.

Application scenario of appearance mode

In general, you can consider using appearance mode in the following cases.

  1. When building a hierarchical system, using appearance patterns to define the entry points of each layer in the subsystem can simplify the dependencies between subsystems.
  2. When a complex system has many subsystems, the appearance pattern can design a simple interface for the system to be accessed by the outside world.
  3. When there is a great connection between the client and multiple subsystems, the appearance pattern can be introduced to separate them, so as to improve the independence and portability of the subsystem.