Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
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
Archives
Today
Total
관리 메뉴

JAVA Developer Training

퍼사드패턴 ( Pacade Pattern ) 본문

디자인패턴

퍼사드패턴 ( Pacade Pattern )

Romenest 2021. 10. 11. 18:11

 

퍼사드 패턴

어떤 서브 시스템의 인터페이스에 대한 통합된 인터페이스를 제공한다. 퍼사드에서 고수준의 인터페이스를 정의

하기 때문에 서브시스템을 더 쉽게 사용할 수 있다.

- 여기서 퍼사드란 프랑스어로 건물의 외관 이라는 뜻을 가지고 있다. 건물의 외관을 본다면 내부의 구조까지는 보이지 않는다는 점을 이해하면 좋을 것이다.

 

즉, 퍼사드 패턴은 많은 서브시스템(내부 구조)을 거대한 클래스(건물 외관)로 감싸서 편리한 인터페이스를 제공해 준다.

사용 이유

여러 구성 요소로 구성된 시스템을 사용자가 작업 수행시 간단한 방법으로 이용하고 싶을때 사용한다

예시로는 온라인 쇼핑몰이 있겠다.

온라인 쇼핑몰의 경우 사용자는 단순히 주문을 하고 싶을 뿐이지 주문하는 행동을 했을때 장바구니 상태는 어째서 이렇게 바뀌었는지 , 쇼핑몰 추천은 이게 어떠한 구조로 떠서 나에게 추천하는 것인지, 결제는 은행사에서 해주는건지 카드사에서 해주는건지 에 대한 정보는 하등 필요가 없다.

따라서 서브시스템(장바구니,추천시스템,결제)을 사용하기 쉽게하는 퍼사드(주문관련 전체를 감싼)를 두어서 간편하게 주문만 넣을 수 있도록 변경 해주는 것이 좋다.

이말인 즉슨 퍼사드 패턴의 핵심은 상호작용 복잡도를 낮춘다는 말이다.

- 퍼사드 패턴을 적용시 서브시스템 클래스에 변화가 생겨도 클라리언트 코드에 영향이 가지않는다.

 

장점
  • 서브 시스템의 복잡성으로 부터 코드를 분리할 수 있다.
  • 서브 시스템으로부터 클라이언트(사용자) 를 보호하고 클라이언트가 서브 시스템을 사용하기 쉽게 만들어준다.
  • 좋게 작성되지 못한 API의 집합을 하나의 좋게 작성된 API로 감싸준다
  • 소프트웨어 라이브러리를 쉽게 사용할 수 있게 해준다.
단점
  • 퍼사드가 어플리케이션의 모든 클래스에 결합된 객체가 될 수 있다.
  • 다른 구성요소에 대한 메소드 호출을 처리하기위해 *래퍼 클래스를 많이 만들어야 할 수도 있다.

*래퍼클래스(Wrapper Class)란 

자바의 자료형에는 크게 기본타입과 참조타입이 있는데 예로

기본타입 - char , int , float, boolean 등이 있고

참조타입 - class , interface 가 있는데

이때 기본 자료타입을 객체로 다루기 위해서 사용하는 클래스들을 래퍼 클래스 라고한다.

래퍼 클래스의 종류에는 아래가 있겠다.

기본타입 래퍼클래스
byte Byte
char Character
int Integer
float Float
double Double
boolean Boolean
long Long
short Shot
예시

사용자가 내부의 구조, 시스템까지 알필요없는 그런 예시를 들어보겠다.

거리에서 흔히 볼 수 있는 자판기로 예를 들어보자

길거리에 자주보이는 자판기는 굉장히 쉽게 사용 할 수 있다.
사용자는 단순히 동전을 투입하고 원하는 음료 밑의 버튼을 누르기만 한다면 음료가 나온다.

이 음료가 나온다 라는 결과는  자판기가 동전이 투입된걸 인식하고 동전의 값어치만큼 수치가 표시되며 그 수치보다 작거나 같은 음료에 한해 버튼을 눌렀을 때 기능이 되게 하고 아니라면 빨간불로 알려주며 기능될 때에는 음료를 밀어서... 와 같은 과정을 거쳐서 나오는 결과다.

그렇다면 사용자는 위와같은 일련의 과정들을 모두 이해해야만 자판기를 사용 할 수 있는가?
전혀 아니다. 그저 음료의 가치와 같거나 높은 가치의 돈을 넣고 버튼을 누르면 음료와 잔돈이 나오는 것 일뿐

만약에 음료를 뽑을때 마다 동전을 얼마넣었는지 기입해야하고 그에 맞게 값보다 높은 음료들은 모두 수작업으로 빨간불로 기능이 작동되지 못하게하며 원하는 음료를 뽑을땐 해당 음료가 밀어서 나와지게 수작업으로 또 해야한다면 자판기는 모조리 없어 졌을 것이다. 복잡하고 귀찮기 때문에

상품은 사용자를 편하게 하기 위함이지 불편하게 하기 위함은 아니기 때문이다.
때문에 기업은 버튼 클릭 하나만으로 원하는 결과를 사용자에게 돌려주기위해 간단한 인터페이스를 제공한다

우선 자판기의 구성을 살펴보자

 


화폐 인식기 - 들어온 화폐의 값어치를 확인해 수치로 바꿔준다

 

쿨러 - 음료가 시원하게 유지되게 해준다

 

스프링 - 기능이 작동될 때 음료를 밀어 배출구로 보낸다


예제 코드

각 기능들을 작동시킬 스위치

public interface Switch{
    public void on();
    public void off();
}

 

화폐 인식기

public class CountMoney implements Switch {

    @Override
    public void off() {
        System.out.println("화폐인식기 꺼짐");
        
    }

    @Override
    public void on() {
        System.out.println("화폐인식기 켜짐");
        
    }
    
}

 

쿨러

public class Cooler implements Switch{

    @Override
    public void off() {
        System.out.println("음료 온도조절 기능 꺼짐");
        
    }

    @Override
    public void on() {
        System.out.println("음료 온도조절 기능 켜짐");
        
    }
    
}

 

스프링

public class Spring implements Switch{

    @Override
    public void off() {
        System.out.println("음료 배출 기능 꺼짐");
        
    }

    @Override
    public void on() {
        System.out.println("음료 배출 기능 켜짐");
        
    }
    
}

만약 우리가 퍼사드 패턴을 사용하지 않는다면 직접 스위치의 on버튼들을 모두 눌러주어야 한다.

화폐인식기 키고, 쿨러도 작동시키고 이후 스프링도 작동시키고 해야한다.

물론 기능을 정지시킬때도 똑같이 모조리 수작업으로 해주어야 할 것이다.

이를 간편하게 사용할 수 있게 퍼사드 패턴을 이용하여

 

퍼사드 클래스 하나를 만들어보자

 

public class VendingFacade{
    CountMoney countMoney;
    Spring spring;
    Cooler cooler;
    Switch[] switchs;
    boolean isActive = false;
    
    public VendingFacade(CountMoney countMoney, Cooler cooler, Spring spring ){
        this.countMoney = countMoney;
        this.cooler = cooler;
        this.spring = spring;
        switchs = new Switch[]{countMoney,cooler,spring};
    }

    public VendingFacade(){
        this.countMoney = new CountMoney();
        this.cooler = new Cooler();
        this.spring = new Spring();
        switchs = new Switch[]{countMoney,cooler,spring};
    }
    

    public void on(){
        for(int i=0; i<switchs.length; i++){
            switchs[i].on();
        }
        isActive= true;
    }

    public void off(){
        for(int i=0; i<switchs.length; i++){
            switchs[i].off();
        }
        isActive= false;
    }
}

 

이제 작동시킬 메인 클래스를 만들어 퍼사드 클래스를 이용해보자

public class Main {
    public static void main(String[] args) {
        VendingFacade facade = new VendingFacade();
        facade.on();
    }
}

 

결과

 

간략한 정리

퍼사드 패턴은 다양하고 복잡한 서브시스템들을 사용자가 버튼하나를 눌러 해결하는 것처럼 편리하게 해결 할 수 있도록 각 시스템들을 퍼사드로 감싸 주는 것이다.

 

굉장히 잘짜여진 퍼사드 패턴은 정말로 버튼 하나만으로 모든 일을 처리할 수 있을지도 모른다.

또한 패턴을 이용하여 간결하게 이용할수도 있으면서 각각의 서브시스템들은 각자 다른곳에서 사용,호출 될수 있다.

세세한 제어를 사용자가 할 수 있다는 점이 장점이 될 수 있지만 세세한 제어 이기 때문에 신중히 사용되어야하고 상관없는 곳에서도 호출될 가능성이 있다는것이 단점이 될 수도 있겠다.

 

주의할 점은 퍼사드 클래스는 서브시스템 클래스들을 캡슐화 하는것이 아니라 

단순히 기능을 편하게 쓰라고 인터페이스를 제공할 뿐이라는 점이다

 

퍼사드 패턴에서 지켜져야할 *최소 지식 원칙(데메테르의 원칙)을 지키는 것도 중요하다 

  • 객체 자체의 메소드만 호출해야한다
  • 메소드에 매개변수로 전달된 객체의 메소드만 호출한다
  • 메소드에서 생성하거나 인스턴스를 만드는 객체의 메소드만 호출한다
  • 객체의 구성요소에 속하는 객체들의 메소드만을 호출한다

이 원칙을 지키면 객체간 의존성을 줄여 결합도를 낮추고 객체지향적인 설계가 가능해진다

간단히말해서 정말 관련있는 객체끼리만 관계를 맺어라는 것이다.