PostCover

디자인 패턴을 쉽게 풀어보자 - 퍼사드 패턴편

GoF의 23가지 디자인 패턴 중 하나인 '퍼사드 패턴(Facade Pattern)'을 쉽게 풀어보기

퍼사드(Facade) 패턴

퍼사드(Facade) 패턴은 복잡한 서브시스템을 단순화하기 위해 하나의 인터페이스로 묶어 제공하는 구조적 디자인 패턴입니다. 여러 클래스와 객체들로 이루어진 복잡한 서브시스템을 클라이언트가 직접 호출하지 않고, 퍼사드 객체를 통해 간편하게 사용할 수 있습니다.

이 패턴은 클라이언트와 서브시스템 간의 결합도를 낮추고, 코드의 가독성과 유지보수성을 높이는 데 유용합니다.

문제점: 복잡한 서브시스템의 사용

어떤 시스템에서 여러 클래스가 서로 협력해야 하는 복잡한 작업이 필요할 수 있습니다. 예를 들어, 오디오, 비디오, 자막 시스템이 따로 동작하는 미디어 플레이어를 생각해봅시다. 클라이언트가 각각의 시스템을 직접 호출해야 한다면, 사용이 불편하고 코드가 복잡해집니다.

class AudioSystem {

    public void initialize() {
        System.out.println("Audio system initialized.");
    }

    public void playAudio() {
        System.out.println("Playing audio.");
    }
}

class VideoSystem {

    public void initialize() {
        System.out.println("Video system initialized.");
    }

    public void playVideo() {
        System.out.println("Playing video.");
    }
}

class SubtitleSystem {

    public void initialize() {
        System.out.println("Subtitle system initialized.");
    }

    public void loadSubtitles(String language) {
        System.out.println("Loading subtitles in: " + language);
    }
}

public class Main {
    public static void main(String[] args) {
        // 클라이언트가 각 시스템을 직접 호출
        AudioSystem audio = new AudioSystem();
        VideoSystem video = new VideoSystem();
        SubtitleSystem subtitle = new SubtitleSystem();

        audio.initialize();
        video.initialize();
        subtitle.initialize();

        audio.playAudio();
        video.playVideo();
        subtitle.loadSubtitles("English");
    }
}

문제점

  • 복잡한 인터페이스: 클라이언트가 여러 클래스를 직접 사용해야 합니다.
  • 유지보수 어려움: 클라이언트와 서브시스템 간의 결합도가 높아, 시스템 변경 시 클라이언트 코드를 수정해야 합니다.
  • 가독성 저하: 여러 시스템을 일관되게 사용하기 어렵습니다.

해결 방법: 퍼사드 패턴 적용

퍼사드 패턴은 여러 서브시스템을 하나의 간단한 인터페이스로 묶어 클라이언트가 편리하게 사용할 수 있도록 합니다. 이로써 클라이언트는 복잡한 내부 구조를 알 필요 없이 퍼사드를 통해 서브시스템을 사용할 수 있습니다.

서브시스템 클래스 정의

class AudioSystem {

    public void initialize() {
        System.out.println("Audio system initialized.");
    }

    public void playAudio() {
        System.out.println("Playing audio.");
    }
}

class VideoSystem {

    public void initialize() {
        System.out.println("Video system initialized.");
    }

    public void playVideo() {
        System.out.println("Playing video.");
    }
}

class SubtitleSystem {

    public void initialize() {
        System.out.println("Subtitle system initialized.");
    }

    public void loadSubtitles(String language) {
        System.out.println("Loading subtitles in: " + language);
    }
}

퍼사드 클래스 정의

class MediaFacade {

    private AudioSystem audio;
    private VideoSystem video;
    private SubtitleSystem subtitle;

    public MediaFacade() {
        this.audio = new AudioSystem();
        this.video = new VideoSystem();
        this.subtitle = new SubtitleSystem();
    }

    // 복잡한 초기화와 재생 과정을 단순화한 메서드 제공
    public void playMedia(String language) {
        audio.initialize();
        video.initialize();
        subtitle.initialize();

        audio.playAudio();
        video.playVideo();
        subtitle.loadSubtitles(language);
    }
}

클라이언트 코드

public class Main {
    public static void main(String[] args) {
        // 클라이언트는 복잡한 서브시스템을 직접 호출하지 않고 퍼사드를 사용
        MediaFacade mediaFacade = new MediaFacade();
        mediaFacade.playMedia("English");
    }
}

퍼사드 패턴의 장단점

장점

  • 결합도 감소: 클라이언트가 서브시스템의 내부 구현에 의존하지 않습니다.
  • 코드 단순화: 복잡한 서브시스템을 단순화하여 가독성을 높이고 유지보수를 쉽게 합니다.
  • 유연성: 서브시스템의 변경이 클라이언트 코드에 영향을 주지 않습니다.
  • 사용 편의성: 클라이언트가 복잡한 서브시스템을 쉽게 사용할 수 있습니다.

단점

  • 기능 제한: 퍼사드가 제공하는 인터페이스 외에 서브시스템의 세부 기능에 접근하기 어렵습니다.
  • 서브시스템과의 의존성: 퍼사드 클래스가 여러 서브시스템에 의존하므로 변경 시 퍼사드 코드도 수정해야 할 수 있습니다.

결론

퍼사드 패턴은 복잡한 서브시스템을 단순화하여 사용자와 시스템 간의 결합도를 낮추고, 코드의 가독성과 유지보수성을 높입니다. 이 패턴은 복잡한 시스템을 쉽게 사용할 수 있도록 도와주며, 서브시스템이 자주 변경되는 상황에서 유용합니다.

하지만, 퍼사드가 제공하는 기능에만 의존하면 세부 기능에 접근하기 어렵다는 단점이 있습니다. 따라서 서브시스템의 확장된 기능이 필요하지 않을 때 사용하는 것이 적합합니다.

퍼사드 패턴은 대규모 시스템에서 유지보수와 확장성을 높이는 강력한 도구로 자주 사용됩니다.