프로그래밍 이론/디자인 패턴

10. [Design Pattern] 퍼사드(Facade) 패턴

NewtronVania 2023. 12. 25. 22:31

퍼사드 패턴

여러 개의 서브 시스템이나 복잡한 클래스들을 간단한 인터페이스를 통해 외부로 노출시키는 패턴. 클라이언트에게 획일화된 하나의 인터페이스를 제공함으로써, 클라이언트는 복잡합 동작 과정을 필요가 없이 인터페이스의 기능을 사용할 있다.


구조

퍼사드 클래스는 다른 패턴에 비해 구조가 비교적 느슨하다


기본 인터페이스

//서브시스템 클래스
class SubSystem1 
{
   public void Method1() { //구현 로직 }
}

class SubSystem2
{
   public void Method2() { //구현 로직 }
}

//퍼사드 클래스
class Facade 
{
   private SubSystem1 sub1;
   private SubSystem2 sub2;

   public Facade() 
   {
      sub1 = new SubSystem1();
      sub2 = new SubSystem2();
   }

   public void FacadeMethod()
   {
      //서브시스템 메서드 호출
      sub1.Method1();  
      sub2.Method2(); 
   }
}

//클라이언트 
class Client
{
    private Facade facade;
    
    public Client()
    {
        facade = new Facade();
    }
    
    public void ClientCode()
    {
        facade.FacadeMethod();
    }
}

왜 사용해야 할까?

간략하게 말하자면 클래스 간의 연동을 캡슐화하는 것이다. 캡슐화가 클래스 내 객체의 상태와 행위를 외부에 감추는 것이라면, 퍼사드는 클래스 간의 의존성과 결합을 외부에 감추고 요청의 결과만을 제공한다. 이를 통해 클라이언트는 상세한 구현에 대해 모른 채 간단한 인터페이스만 제공받을 수 있다.

이에 대해 컴퓨터를 실행하는 과정을 예로 들어보자. 컴퓨터를 실행하는 데 우리가 하는 과정은 딱 하나, 실행 버튼을 누르는 것이다.

public class Client {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}

하지만 깊이 들어가면 컴퓨터를 실행하는 데엔 여러 동작이 필요하다. 먼저 컴퓨터를 구성하는  CPU, Memory, HardDrive,같은 기본적인 부품이 필요하다. 부품들은 각자 독립적으로 행동하기도, 때론 연결되어 동작하기도 것이다.

// 서브 시스템 클래스들
class CPU {
    public void freeze() { System.out.println("CPU freeze"); }
    public void jump() { System.out.println("CPU jump"); }
    public void execute() { System.out.println("CPU execute"); }
}

class Memory {
    public void load() { System.out.println("Memory load"); }
}

class HardDrive {
    public void read() { System.out.println("HardDrive read"); }
}

컴퓨터는 부품들을 이용해 실행 명령을 수행한다. CPU 불러오고, Memory 통해 데이터를 불러오며, HardDrive 통해 가져온 데이터를 읽고 CPU 실행시키는 컴퓨터 실행의 전반적인 동작 과정이다.

 

// 퍼사드 클래스
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void start() {
        cpu.freeze();
        memory.load();
        cpu.jump();
        hardDrive.read();
        cpu.execute();
    }
}

클라이언트는 CPU, Memory, HardDrive 같은 클래스에 대해 전혀 모르는 상태이지만, 퍼사드 클래스에서 해당 클래스간의 연계, 복잡성 등을 숨기고 실행함으로써 클라이언트에게 간단한 방식으로 똑같은 서비스를 제공할 있다

 

장점

  1. 사용자에게 간단한 인터페이스만 제공할 수 있다.
  2. 하위 시스템 간의 의존관계가 많은 경우 퍼사드 패턴에 의존성을 집중시킬 수 있다.
  3. 시스템의 동작을 계층화할 수 있다.

단점

  1. 모든 클래스와 결합된 전지전능한 클래스가 될 수 있다.
  2. 퍼사드 클래스 자체가 서브 클래스에 대해 의존성을 갖게 된다.
  3. 유지보수 자체가 해결되지 않았다. 퍼사드 패턴을 확장해야 할 경우 의존성 관계 때문에 유지보수가 힘들어질 수 있다.

전체 예시 코드

// 퍼사드 클래스
class ComputerFacade {
    private CPU cpu;
    private Memory memory;
    private HardDrive hardDrive;

    public ComputerFacade() {
        this.cpu = new CPU();
        this.memory = new Memory();
        this.hardDrive = new HardDrive();
    }

    public void start() {
        cpu.freeze();
        memory.load();
        cpu.jump();
        hardDrive.read();
        cpu.execute();
    }
}

// 서브 시스템 클래스들
class CPU {
    public void freeze() { System.out.println("CPU freeze"); }
    public void jump() { System.out.println("CPU jump"); }
    public void execute() { System.out.println("CPU execute"); }
}

class Memory {
    public void load() { System.out.println("Memory load"); }
}

class HardDrive {
    public void read() { System.out.println("HardDrive read"); }
}

// 클라이언트 코드
public class Client {
    public static void main(String[] args) {
        ComputerFacade computer = new ComputerFacade();
        computer.start();
    }
}
CPU freeze
Memory load
CPU jump
HardDrive read
CPU execute

참고자료

 

GoF의 디자인 패턴 - 예스24

이 책은 디자인 패턴을 다룬 이론서로 디자인 패턴의 기초적이고 전반적인 내용을 학습할 수 있다.

www.yes24.com