Facade Pattern

📢 This article was translated by gemini-3-flash-preview

Facade Pattern: Object Structural Pattern

Intent

Provide a unified interface to a set of interfaces in a subsystem. Facade defines a higher-level interface that makes the subsystem easier to use.

Structure

Facade Pattern

Participants:

  • Facade: Knows which subsystem classes are responsible for a request; delegates client requests to appropriate subsystem objects.
  • Subsystem classes: Implement subsystem functionality; handle work assigned by the Facade object; have no knowledge of the Facade (i.e., they keep no reference to it).

Applicability

Use the Facade pattern when:

  • You want to provide a simple interface to a complex subsystem. Subsystems often get more complex as they evolve. Most patterns result in more but smaller classes, making the subsystem more reusable and easier to customize, but harder to use for clients that don’t need customization. A facade provides a simple default view that is good enough for most users.
  • There are many dependencies between clients and the implementation classes of an abstraction. Introducing a facade decouples the subsystem from clients and other subsystems, improving independence and portability.
  • You want to layer your subsystems. Use a facade to define an entry point to each subsystem level. If subsystems are dependent, they can communicate solely through their facades, simplifying the dependencies between them.

Example 1

Think of a hospital. To get treatment, a patient usually interacts with various departments: registration, outpatient, pharmacy, etc. To simplify this, a receptionist role can be introduced to handle these steps for the patient. The patient only needs to interact with the receptionist.

Facade - Hospital Example - Class Diagram

Java Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
import java.util.*;

interface Patient {
    public String getName();
}

interface Disposer {
    public void dispose(Patient patient);
}

class Registry implements Disposer { // Registration
    public void dispose(Patient patient) {
        System.out.println("I am registering..." + patient.getName());
    }
}

class Doctor implements Disposer { // Outpatient Doctor
    public void dispose(Patient patient) {
        System.out.println("I am diagnosing..." + patient.getName());
    }
}

class Pharmacy implements Disposer { // Pharmacy
    public void dispose(Patient patient) {
        System.out.println("I am medicine... " + patient.getName());
    }
}

class Facade {
    private Patient patient;

    public Facade(Patient patient) {
        this.patient = patient;
    }

    void dispose() {
        Registry registry = new Registry();
        Doctor doctor = new Doctor();
        Pharmacy pharmacy = new Pharmacy();

        registry.dispose(patient);
        doctor.dispose(patient);
        pharmacy.dispose(patient);
    }
}

class ConcretePatient implements Patient {
    private String name;

    public ConcretePatient(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}

public class FacadeTest {
    public static void main(String[] args) {
        Patient patient = new ConcretePatient("zst");
        Facade f = new Facade(patient);
        
        f.dispose();
    }
}

C++ Code

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
#include <iostream>
#include <string>

using namespace std;

class Patient {
public:
    virtual string getName() = 0;
};

class Disposer {
public:
    virtual void dispose(Patient *patient) = 0;
};

class Registry : public Disposer { // Registration
public:
    void dispose(Patient *patient) {
        cout << "I am registering...." << patient->getName() << endl;
    }
};

class Doctor : public Disposer { // Outpatient Doctor
public:
    void dispose(Patient *patient) {
        cout << "I am diagnosing...." << patient->getName() << endl;
    }
};

class Pharmacy : public Disposer { // Pharmacy
public:
    void dispose(Patient *patient) {
        cout << "I am giving medicine...." << patient->getName() << endl;
    }
};

class Facade {
private:
    Patient *patient;

public:
    Facade(Patient *patient) { this->patient = patient; }

    void dispose() {
        Registry *registry = new Registry();
        Doctor *doctor = new Doctor();
        Pharmacy *pharmacy = new Pharmacy();

        registry->dispose(patient);
        doctor->dispose(patient);
        pharmacy->dispose(patient);
    }
};

class ConcretePatient : public Patient {
private:
    string name;

public:
    ConcretePatient(string name) { this->name = name; }

    string getName() { return name; }
};

int main() {
    Patient *patient = new ConcretePatient("zst");
    Facade *f = new Facade(patient);

    f->dispose();

    return 0;
}

Example 2

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
public class FacadePattern {
    public static void main(String[] args) {
        Facade f = new Facade();

        f.methodA();
    }
}

class Facade{
    SubSystemOne s1;
    SubSystemTwo s2;
    SubSystemThree s3;

    public Facade(){
        s1 = new SubSystemOne();
        s2 = new SubSystemTwo();
        s3 = new SubSystemThree();
    }

    public void methodA(){
        s1.Operation();
    }

    public void methodB(){
        s2.Operation();
    }

    public void methodC(){
        s3.Operation();
    }
}

class SubSystemOne{
    public void Operation(){
        System.out.println("SubSystemOne");
    }
}

class SubSystemTwo{
    public void Operation(){
        System.out.println("SubSystemTwo");
    }
}

class SubSystemThree{
    public void Operation(){
        System.out.println("SubSystemThree");
    }
}