Facade mode — Facade

Facade mode-Facade

1. Pattern definition:

Facade mode (Facade): It is required that the communication between the outside of a subsystem and its inside must be carried out through a unified object. The facade mode provides a high-level interface, making the subsystem easier to use .

2. Schema structure

  • Facade: facade class
  • Subsystem Collection:
  • SubSystemA: Subsystem A
  • SubSystemB: Subsystem B
  • SubSystemC: Subsystem C
  • Context: Composite Subsystem

3. Code Analysis

  • 3.1 main.cpp
#include<iostream>
#include "facade.hpp"
using namespace std;

int main(int argc, char const *argv[])
{
    Facade facade;
    facade. methodA();
    facade.methodB();
    facade. methodC();

    return 0;
}

  • 3.2 Facade class: facade.hpp
#ifndef FACADE_HPP
#define FACADE_HPP

#include "subsystem.hpp"

// facade class
class Facade
{
private:
    SubSystemA* a;
    SubSystemB* b;
    Context* c;
public:
    Facade(){
        a = new SubSystemA();
        b = new SubSystemB();
        c = new Context();
    }
    ~Facade(){
        delete a;
        delete b;
        delete c;
    }

    void methodA() {
        a->doSomethingA();
    }

    void methodB() {
        b->doSomethingB();
    }

    void methodC() {
        c->complexMethod();
    }
};

#endif // FACADE_HPP
  • 3.3 Experimental results:
SubSystemA::doSomethingA
SubSystemB::doSomethingB
SubSystemA::doSomethingA
SubSystemC::doSomethingC

4. Advantages and disadvantages

  • 4.1 Advantages

    • 4.1.1 Shielding subsystem components from clients reduces the number of objects handled by clients and makes the subsystem easier to use. By introducing the Facade pattern, the client code will be very simple with few objects associated with it.
    • 4.1.2 The loose coupling relationship between the subsystem and the client is realized, which makes the component change of the subsystem not affect the client class that calls it, and only needs to adjust the appearance class
    • 4.1.3 Reduce the compilation dependency in large-scale software systems, and simplify the process of transplanting the system between different platforms, because the compilation A subsystem generally does not need to compile all other subsystems. Modifications to one subsystem have no effect on other subsystems, and subsystem internal changes do not affect appearance objects.
    • 4.1.4 It only provides a unified entry to access the subsystem, and does not affect the user’s direct use of the subsystem class
  • 4.2 Disadvantages

    • 4.2.1 The use of subsystem classes by customers cannot be well restricted. If there are too many restrictions on customers’ access to subsystem classes, the variability and flexibility will be reduced.
    • 4.2.2 In the case of not introducing an abstract appearance class, adding a new subsystem may require modifying the source code of the appearance class or the client, which violates the “open-closed principle”.

5. Pattern analysis

  • 5.1 The facade class provides a unified access interface for the client, so that the changes of the subsystem are isolated internally and do not affect the access interface of the client;

  • 5.2 The facade mode is also the embodiment of “Dimit’s law“. By introducing a new appearance class, the complexity of the original system can be reduced, and at the same time, reduce customer classes and subsystems The coupling degree of the class;

  • 5.3 The purpose of the facade mode is to reduce the complexity of the subsystem set and provide the convenience of the client.

6. Example: write and send a letter (go code implementation)

  • Class Diagram:

  • 6.0: main.go

package main

import (
"fmt"
"./facade"
)

func test_facade() {<!-- -->
hellPost := facade. NewModenPostOffice(facade. NewLetterProcessImp())
context := "Hello, wilim! How arr you recently..."
address := "HuaFu Street, No.3"
hellPost. SendLetter(context, address)
}

func main() {<!-- -->
test_facade()
}
  • 6.1: Letter processing process interface: ILetterProcess.go
package facade

// Letter processing process interface
type ILetterProcess interface {<!-- -->
WriteLetter(context string)
FillEnvelope(address string)
LetterIntoEnvelope()
SendLetter()
}

  • 6.2: Subsystem – Letter Processing Process: LetterProcessImp.go
package facade

import "fmt"

type LetterProcessImp struct {<!-- -->
}

func NewLetterProcessImp() *LetterProcessImp {<!-- -->
return & LetterProcessImp{<!-- -->}
}

func (lpi *LetterProcessImp) WriteLetter(context string) {<!-- -->
fmt.Println("LetterProcessImp::WriteLetter: ", context)
}

func (lpi *LetterProcessImp) FillEnvelope(address string) {<!-- -->
fmt.Println("LetterProcessImp::FillEnvelope: ", address)
}

func (lpi *LetterProcessImp) LetterIntoEnvelope() {<!-- -->
fmt.Println("LetterProcessImp::LetterIntoEnvelope")
}

func (lpi *LetterProcessImp) SendLetter() {<!-- -->
fmt.Println("LetterProcessImp::SendLetter")
}

  • 6.3: Subsystem – Check Letters: Police.go
package facade

import "fmt"

type Police struct {<!-- -->
}

func NewPolice() *Police {<!-- -->
return &Police{<!-- -->}
}

func (p *Police) CheckLetter(context string) {<!-- -->
fmt.Println("Police::CheckLetter: ", context)
}
  • 6.4: Facade Class – Modern Post Office: ModenPostOffice.go
package facade

type ModenPostOffice struct {<!-- -->
letterProcess ILetterProcess
policepolice
}

func NewModenPostOffice(letterProcess ILetterProcess) *ModenPostOffice {<!-- -->
return & ModenPostOffice{<!-- -->
letterProcess: letterProcess,
}
}

func (mpo *ModenPostOffice) SendLetter(context, address string) {<!-- -->
mpo. letterProcess. WriteLetter(context)
mpo. letterProcess. FillEnvelope(address)
mpo.police.CheckLetter(context + "<->" + address)
mpo.letterProcess.LetterIntoEnvelope()
mpo. letterProcess. SendLetter()
}
  • 6.5 Execution result:
LetterProcessImp::WriteLetter: Hello, wilim! How arr you recentlylly...
LetterProcessImp::FillEnvelope: HuaFu Street, No.3
Police::CheckLetter: Hello, wilim! How arr you recently...<->HuaFu Street,No.3
LetterProcessImp::LetterIntoEnvelope
LetterProcessImp::SendLetter