본문으로 건너뛰기

디자인 패턴 - 퍼사드 패턴 (Facade Pattern)

무료2015-03-07#Design_Pattern#外观模式#Facade Pattern

퍼사드 패턴은 복잡한 서브시스템에 대해 간단하고 사용하기 쉬운 고수준 인터페이스를 제공하는 데 사용됩니다. 서브시스템에서 간단한 기능을 구현하기 위해 많은 저수준 컴포넌트를 호출해야 한다고 느낀다면, 퍼사드 패턴이 도움이 될 것입니다.

no_mkd

일. 퍼사드 패턴이란?

간단히 말해, 퍼사드 패턴은 인터페이스를 단순화하는 데 사용됩니다.

보통 서브시스템이 사용하기 어렵다고 느끼는 이유는, 해당 서브시스템이 제공하는 외부 인터페이스가 저수준 컴포넌트에 너무 가까워서 불편하게 느끼기 때문입니다.

내부 세부사항을 알 필요는 없으며, "원버튼으로 완료"되는 기능이 필요할 뿐입니다. 서브시스템의 메서드 하나를 호출하면 이미지 전처리를 대신 수행해 줍니다. 회색조 변환 메서드, 이미지 향상 알고리즘, 노이즈 처리 메서드 등을 하나씩 직접 호출하여 전처리를 구현할 필요가 없습니다.

서브시스템이 제공하는 인터페이스가 저수준 컴포넌트에 너무 가까우면, 사용하기 어려울 뿐만 아니라 서브시스템의 캡슐화도 손상됩니다 (서브시스템을 호출하려면 해당 저수준 컴포넌트 각각을 이해해야 하며, 알 필요 없는 세부사항까지 알게 됩니다..)

이. 예시

캡슐화된 오래된 세탁기가 있다고 가정해 봅시다. 다음과 같은 외부 인터페이스를 제공합니다:

package FacadePattern;

/**

  • @author ayqy

  • 세탁기 인터페이스 정의 / public interface Washer { /

    • 공통 부분
    • */ //전원에 연결 public abstract boolean connectToPower();

    /*

    • 세탁 부분
    • */ //왼쪽 세탁조 열기 public abstract void openLeftSide(); //급수구 열기 public abstract void openWaterHole(); //급수 시작 public abstract void startWaterInjection(); //급수 중지 public abstract void stopWaterInjection(); //왼쪽 세탁조 회전 시작 public abstract void startWashing(); //왼쪽 세탁조 회전 중지 public abstract void stopWashing();

    /*

    • 탈수 부분
    • */ //오른쪽 탈수조 열기 public abstract void openRightSide(); //오른쪽 탈수조 회전 시작 public abstract void startDewatering(); //오른쪽 탈수조 회전 중지 public abstract void stopDewatering();

    /*

    • 배수 부분은 생략..
    • */ }

어쩔 수 없습니다. 정말 너무 오래되어 현대 생활에는 만족스럽지 않지만, 새로운 자동화 세탁기를 살 여유는 없으므로, 반자동 세탁기로 바꾸고 아낀 시간으로 코드를 작성해야 합니다.. 먼저 오래된 세탁기로 세탁하는 방법을 살펴보겠습니다:

package FacadePattern;

/**

  • @author ayqy

  • 오래된 세탁기로 세탁하기 */ public class Washing implements Washer{

    public static void main(String[] args) { //세탁기 객체 생성 Washer washer = new Washing(); //전원에 연결 if(washer.connectToPower()){ //세탁조 열기 washer.openLeftSide(); /더러운 옷을 넣는 과정 생략/ //급수구 열기 washer.openWaterHole(); //급수 시작 washer.startWaterInjection(); /5 분 대기/ //급수 중지 washer.stopWaterInjection(); /세제 추가 과정 생략/ //세탁 시작 washer.startWashing(); /15 분 후 중지/ washer.stopWashing();

     	/*
     	 * 탈수 부분은 생략
     	 * */
     }
    

    }

    /*

    • 아래는 자동 생성된 것이니 무시하세요..
    • */ @Override public boolean connectToPower() { // TODO Auto-generated method stub return false; }

    @Override public void openLeftSide() { // TODO Auto-generated method stub

    }

    @Override public void openWaterHole() { // TODO Auto-generated method stub

    }

    @Override public void startWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void stopWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void startWashing() { // TODO Auto-generated method stub

    }

    @Override public void stopWashing() { // TODO Auto-generated method stub

    }

    @Override public void openRightSide() { // TODO Auto-generated method stub

    }

    @Override public void startDewatering() { // TODO Auto-generated method stub

    }

    @Override public void stopDewatering() { // TODO Auto-generated method stub

    }

}

세탁하는 과정을 조금 시연했을 뿐인데, 이렇게 많은 조작을 호출해야 했습니다. 게다가 이 세탁기의 내부 세부사항을 모르면 아예 사용할 수조차 없습니다.. 세탁에는 60 분이 걸릴 수 있습니다 (급수 + 세탁 + 탈수 + 배수). 그 동안에는 거의 아무것도 할 수 없고, 세탁기 옆에서 쪼그려 앉아 끊임없이 기계를 조작해야 합니다

리모컨이 필요할 것 같습니다. 버튼이 2 개 있습니다:

  • 세탁
  • 탈수

그럼 세탁 과정은 다음과 같이 변합니다:

  1. 세탁 버튼을 누르면 자동으로 전원에 연결되고, 자동으로 세탁조가 열리며, 자동으로 5 분간 급수하고, 자동으로 15 분간 세탁합니다
  2. 탈수 버튼을 누르면 자동으로 탈수조가 열리고, 자동으로 10 분간 탈수하며, 자동으로 배수하고, 자동으로 전원이 차단됩니다

정말 훌륭합니다. 점심 식사 전에 세탁 버튼을 한 번 누르고, 다 먹은 후 옷을 오른쪽으로 가져가서 탈수 버튼을 한 번 누른 다음 출근하면, 오후에 돌아와서 옷을 널면 됩니다 (물론, 수동으로 옷을 왼쪽에서 오른쪽으로 가져가는 과정은 피할 수 없지만, 정말 오래되어 전자동 세탁기가 되는 것은 기대할 수 없습니다..)

우리가 만든 리모컨을 살펴보겠습니다:

package FacadePattern;

/**

  • @author ayqy

  • 리모컨 (일명 퍼사드) */ public class WasherFacade { private Washer washer;

    public WasherFacade(Washer washer){ this.washer = washer; }

    /**

    • 자동 세탁 */ public void washing(){ //전원에 연결 if(washer.connectToPower()){ //세탁조 열기 washer.openLeftSide(); /더러운 옷을 넣는 과정 생략/ //급수구 열기 washer.openWaterHole(); //급수 시작 washer.startWaterInjection(); /5 분 대기/ //급수 중지 washer.stopWaterInjection(); /세제 추가 과정 생략/ //세탁 시작 washer.startWashing(); /15 분 후 중지/ washer.stopWashing(); } }

    /**

    • 자동 탈수 */ public void dewashing(){ /전원 연결 여부 판단 과정 생략/ //오른쪽 탈수조 열기 washer.openRightSide(); //오른쪽 탈수조 회전 시작 washer.startDewatering(); //오른쪽 탈수조 회전 중지 washer.stopDewatering();

      /*

      • 배수 과정 생략
      • 전원 차단 과정 생략
      • */ } }

리모컨이 있으면 세탁은 다음과 같이 합니다:

package FacadePattern;

/**

  • @author ayqy

  • 퍼사드 패턴을 적용한 반자동 세탁기 테스트 (리모컨 활용) */ public class Test implements Washer{

    public static void main(String[] args) { //오래된 세탁기 생성 Washer washer = new Test(); //퍼사드 (리모컨) 생성 WasherFacade facade = new WasherFacade(washer); //세탁 버튼 눌러 세탁 시작 facade.washing(); /옷을 다른 쪽으로 가져가기/ //탈수 버튼 눌러 탈수 시작 facade.dewashing(); }

    /*

    • 아래는 자동 생성된 것이니 무시하세요..
    • */ @Override public boolean connectToPower() { // TODO Auto-generated method stub return false; }

    @Override public void openLeftSide() { // TODO Auto-generated method stub

    }

    @Override public void openWaterHole() { // TODO Auto-generated method stub

    }

    @Override public void startWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void stopWaterInjection() { // TODO Auto-generated method stub

    }

    @Override public void startWashing() { // TODO Auto-generated method stub

    }

    @Override public void stopWashing() { // TODO Auto-generated method stub

    }

    @Override public void openRightSide() { // TODO Auto-generated method stub

    }

    @Override public void startDewatering() { // TODO Auto-generated method stub

    }

    @Override public void stopDewatering() { // TODO Auto-generated method stub

    }

}

정말 편하고 좋지만, 자세히 보면 메서드 호출을 캡슐화하기 위해 두 개의 메서드를 정의한 것뿐입니다. 무엇이 대단할까요? 새로운 프로젝트 코드에서 세탁과 탈수를 담당하는 두 개의 메서드를 정의하는 것과 무엇이 다를까요? 물론 다릅니다. 조급해하지 마세요.

삼. 퍼사드 패턴의 장점

  1. 낮은 결합도

    먼저 명명 방식을 살펴보겠습니다. 리모컨의 이름은 WasherFacade 입니다. 모듈을 나눈다면 Washer 와 함께 두어야 할 것입니다. 맞습니다. Facade 를 정의함으로써 Washer 와 코드의 결합을 성공적으로 분리했습니다. 즉, Washer 에 변경이 발생하면 긴 프로젝트 코드에서 두 개의 메서드를 찾는 대신 Facade 를 직접 수정하면 됩니다

  2. 서브시스템의 캡슐화 보호

    캡슐화된 Washer 를 열어 수정한 것이 아닙니다. Washer 의 인터페이스를 단순화하기 위해 몇 줄의 코드를 추가했을 뿐입니다. 이전에는 호출자가 Washer 의 내부를 잘 알고 있었지만, 이제는 Washer 에 대해 거의 아무것도 모릅니다 (생성자 제외)

  3. 여러 다른 객체를 포함한 서브시스템에 적합

    예시의 Washer 는 단일 객체일 뿐이므로, 이러한 간단한 인터페이스는 Washer 자체가 제공해야 할 수도 있습니다. 하지만 일상 생활의 반자동화를 구현하려면 여러 객체를 다루게 됩니다. 예를 들어 문, 창문, 커튼, TV, 전자레인지, 세탁기, 컴퓨터 등입니다. 원버튼으로 아침 식사 준비 (자동 점등, 전자레인지로 자동 가열), 원버튼으로 낮잠 (자동으로 문 닫기, 자동으로 커튼 치기, 자동으로 소등) 등의 기능을 구현하고 싶을 때 퍼사드 패턴이同样하게 적용됩니다: 퍼사드가 몇 개의 구체적인 객체를 더 가지게 하면 됩니다

  4. 서브시스템의 인터페이스를 효과적으로 단순화

    이전에는 세탁할 때 세탁기 옆에서 쪼그려 앉아 끊임없이 조작해야 했지만, 이제는 "원버튼으로 완료"할 수 있습니다. 이것이 바로 우리가 원하는 간단하고 사용하기 쉬운 인터페이스입니다

  5. "최소 지식 원칙" 충족

    "친구와만 대화하기"를 실천했습니다. 새로운 시스템은 Facade 만 알고 있으며, 그것과만 대화하고, 서브시스템 내의 많은 저수준 컴포넌트와 대화하기 위해 이리저리 돌아다니지 않습니다

사. 요약

퍼사드 패턴은 복잡한 서브시스템에 대해 간단하고 사용하기 쉬운 고수준 인터페이스를 제공하는 데 사용됩니다.

많은 저수준 컴포넌트에 시달려 벗어날 수 없을 때, 리모컨을 만들어 보세요. 정말로 그것이 필요할 것입니다..

댓글

아직 댓글이 없습니다

댓글 작성