데먕 2020. 2. 24. 22:03

1. Overview

Facade is an object that serves as a front-facing interface masking more complex underlying or structural code. A facade can:

  • Improve the readability and usability of a software library by masking interaction with more complex components behind a single (and often simplified) API
  • Provide a context-specific interface to more generic functionality (complete with context-specific input validation)
  • Serve as a launching point for a broader refactor of monolithic or tightly-coupled systems in favor of more loosely-coupled code

A client has to interact with a large number of interfaces and classes in a subsystem to get a result. So the client gets tightly coupled with those interfaces & classes. Facade solves these problems.

Facade provides a simple and unified interface to a subsystem. The client interacts with just the face now to get the same result.

Facade is not just a one to one method forwarding to other classes.

2. Description

2.1 Motivation

  • Balancing complexity and presentation usability
  • API consumers want it to just work even though many systems working to provide flexibility.
  • Facade provides a simple, easy to understand user interface over a large and sophisticated body of code.

2.2 Code Example

class Buffer {
    private char [] characters;
    private int lineWidth;

    public Buffer(int lineHeight, int lineWidth) {
        this.characters = new char[lineWidth*lineHeight];
        this.lineWidth = lineWidth;
    }

    public char charAt(int x, int y) {
        return characters[y*lineWidth + x];
    }
}

class Viewport {
    private final Buffer buffer;
    private final int width;
    private final int height;
    private final int offsetX;
    private final int offsetY;

    public Viewport(Buffer buffer, int width, int height, int offsetX, int offsetY) {
        this.buffer = buffer;
        this.width = width;
        this.height = height;
        this.offsetX = offsetX;
        this.offsetY = offsetY;
    }

    public char charAt(int x, int y) {
        return buffer.charAt(x+offsetX, y+offsetY);
    }
}

class Console {
    private List<Viewport> viewports = new ArrayList<>();
    int width, height;

    public Console(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public void addViewPort(Viewport viewport) {
        viewports.add(viewport);
    }
    // Facade
    public static Console newConsole(int width, int height) {
        Buffer buffer = new Buffer(width, height);
        Viewport viewport = new Viewport(buffer, width, height, 0, 0);
        Console console = new Console(width, height);
        console.addViewPort(viewport);
        return console;
    }
    public void render() {
        for (int y = 0; y < height; ++y) {
            for (int x = 0; x < width; ++x) {
                for (Viewport vp: viewports) {
                    System.out.println(vp.charAt(x, y));
                }
                System.out.println();
            }
        }
    }
}

public class Demo {
    public static void main(String[] args) {
        // without facade
        Buffer buffer = new Buffer(30, 20);
        Viewport viewport = new Viewport(buffer, 30, 20, 0, 0);
        Console console = new Console(30, 20);
        console.addViewPort(viewport);
        console.render();

        // with facade
        Console console2 = Console.newConsole(30, 20);
        console2.render();
    }
}

3. Reference

https://en.wikipedia.org/wiki/Facade_pattern