퍼사드 패턴(Facade Pattern)

박세건·2024년 5월 21일
0

디자인 패턴

목록 보기
6/17
post-thumbnail

퍼사드 패턴이란, 사용하기 복잡한 라이브러리들을 사용하기 편리하도록 간편한 인터페이스를 구성하기위한 구조패턴이다
라이브러리의 클래스와 메서드의 동작을 바로 이해하기 어려워 사용하기 어려울때, 이에 대해서 적절한 네이밍과 정리를 통해 사용자들이 쉽게 하용할 수 있도록 인터페이스를 생성
이를 통해서 개발자의 실수를 방지할 수 있다
교제를 보고 이해하기 쉽도록 노트에 재정리하는 행위와 비슷
사용자는 간단하게 구성된 인터페이스를 사용해서 내부의 복잡한 시스템에 상관없이 기능을 사용 가능

Facade : 정면을 의미 -> 건축의 정면을 보고 건축의 목적을 바로 알 수 있음

구조

  • 퍼사드 패턴은 다른 디자인 패턴들과 다르게 클래스 구조가 정형화 되지 않은 패턴
  • 반드시 어떤 형식을 따라야하는 규칙같은것이 존재하지 않음
  • 퍼사드 클래스를 만들어 적절하게 기능들을 묶어줌

그림에서 볼 수 있듯이 클라이언트는 Facade만 보고 기능을 사용하고 내부의 복잡한 로직을 신경쓰지 않는다.

재귀적인 Facade 패턴 적용

위에 그림에서 보면 클라이언트가 Facade를 사용해서 내부 복잡한 시스템을 간다하게 사용하는데 사용되는 서브 클래스들은 또 다른 Facade 클래스가 될 수 있고 이렇게 만들어진 또 다른 Facade 패턴은 다시 다른 Facade에 의해 사용될 수 있다.

사용 시기

  • 시스템이 복잡할때
  • 복잡한 시스템을 간단한 인터페이스로 해결하고자 할때
  • 결합도가 높아 의존성을 낮추기 위해

장점

  • 복잡한 시스템을 내부에서 사용하기 편리
  • 의존관계가 복잡할 경우 이를 간단하게 처리하고 의존성을 모을 수 있다.
  • 사용자는 Facade만 알고 있으면 내부 로직을 몰라도 사용 가능

내부의 로직이 변경되어야 하는 상황이 생겨도 사용자는 Facade만 따르면 되기때문에 상관이 없어지고 의존성이 감소됩니다.

단점

  • 퍼사드 클래스가 모든 클래스에 결합된 GOD 객체가 될 수 있다

    GOD(신) 객체

  • 하나의 클래스의 여러 개의 책임이 있는 클래스

  • SOLID 5대원칙중 SRP원칙을 위반

  • 퍼사드 객체는 서브 시스템에 대한 의존성을 갖게되어 의존성을 완전히 무시할 수는 없다

  • Facade 클래스를 설계하면 코드가 늘어나기 때문에 유지보수 비용이 더 많이 든다
    - 때문에 Facade를 추가해서 얻게되는 이점과 추가적인 유지보수 비용을 비교하여 결정

예시

DB관련 라이브러리를 사용하는 코드가 main에 그대로 작성된 코드

class Client {
    public static void main(String[] args) {
        // 1. 데이터베이스 생성 & 등록
        DBMS dbms = new DBMS();
        dbms.put("홍길동", new Row("홍길동", "1890-02-14", "honggildong@naver.com"));
        dbms.put("임꺽정", new Row("임꺽정", "1820-11-02", "imgguckjong@naver.com"));
        dbms.put("주몽", new Row("주몽", "710-08-27", "jumong@naver.com"));

        // 2. 캐시 생성
        Cache cache = new Cache();

        // 3. 트랜잭션에 앞서 먼저 캐시에 데이터가 있는지 조회
        String name = "홍길동";
        Row row = cache.get(name);

        // 4. 만약 캐시에 없다면
        if (row == null){
            row = dbms.query(name); // DB에 해당 데이터를 조회해서 row에 저장하고
            if(row != null) {
                cache.put(row); // 캐시에 저장
            }
        }

        // 5. dbms.query(name)에서 조회된 값이 있으면
        if(row != null) {
            Message message = new Message(row);

            System.out.println(message.makeName());
            System.out.println(message.makeBirthday());
            System.out.println(message.makeEmail());
        }
        // 6. 조회된 값이 없으면
        else {
            System.out.println(name + " 가 데이터베이스에 존재하지 않습니다.");
        }
    }
}

Facade 객체를 통해서 간단하게 사용할 수 있는 인터페이스 제공

class Facade {
    private DBMS dbms = new DBMS();
    private Cache cache = new Cache();

    public void insert() {
        dbms.put("홍길동", new Row("홍길동", "1890-02-14", "honggildong@naver.com"));
        dbms.put("임꺽정", new Row("임꺽정", "1820-11-02", "imgguckjong@naver.com"));
        dbms.put("주몽", new Row("주몽", "710-08-27", "jumong@naver.com"));
    }

    public void run(String name) {
        Row row = cache.get(name);

        // 1. 만약 캐시에 없다면
        if (row == null){
            row = dbms.query(name); // DB에 해당 데이터를 조회해서 row에 저장하고
            if(row != null) {
                cache.put(row); // 캐시에 저장
            }
        }

        // 2. dbms.query(name)에서 조회된 값이 있으면
        if(row != null) {
            Message message = new Message(row);

            System.out.println(message.makeName());
            System.out.println(message.makeBirthday());
            System.out.println(message.makeEmail());
        }
        // 3. 조회된 값이 없으면
        else {
            System.out.println(name + " 가 데이터베이스에 존재하지 않습니다.");
        }
    }
}
class Client {
    public static void main(String[] args) {

        // 1. 퍼사드 객체 생성
        Facade facade = new Facade();

        // 2. db 값 insert
        facade.insert();

        // 3. 퍼사드로 데이터베이스 & 캐싱 & 메세징 로직을 한번에 조회
        String name = "홍길동";
        facade.run(name);
    }
}

중요한점은 Facade를 구성하는 기능을 적게 구성하는 것이다. 만약 Facade를 구성하는 기능들이 많아진다면 사용자는 똑같은 복잡함을 느끼게 될 것이다.

profile
멋있는 사람 - 일단 하자

0개의 댓글