관리 메뉴

나만을 위한 블로그

자바 - 퍼사드 패턴(Facade Pattern)이란? 본문

개인 공부/디자인 패턴

자바 - 퍼사드 패턴(Facade Pattern)이란?

참깨빵위에참깨빵 2020. 11. 25. 01:02
728x90
반응형

파카드 패턴이라고 읽을 것 같은데 퍼사드라고 읽는다

이번 포스팅에선 디자인 패턴 중 퍼사드 패턴에 대해서 포스팅해보려고 한다.

그 전에 퍼사드는 무슨 뜻이 있는지 먼저 확인해보자.

 

Facade : (건물의) 정면, 앞면 / (실제와 다른) 표면, 허울

 

정면이거나 진짜가 아닌 다른 것? 정도의 뜻이 있는 듯하다.

다음은 영문 위키백과의 내용이다.

 

(중략) 건축의 파사드와 유사하게 파사드는 더 복잡한 기본 또는 구조 코드를 마스킹하는 전면 인터페이스 역할을 하는 객체다. 퍼사드는 아래의 내용들을 수행할 수 있다.

- 단일(또는 단순화된) API 뒤에 있는 더 복잡한 구성요소와의 상호작용을 마스킹해서, 소프트웨어 라이브러리의 가독성과 유용성을 개선
- 일반적인 기능에 대한 컨텍스트 별 인터페이스 제공
- 느슨하게 결합된 코드를 선호하는 모놀리틱(Monolithic) 또는 긴밀하게 결합된 시스템의 광범위한 리팩토링을 위한 시작점 역할

개발자는 시스템이 복잡하거나 상호의존적인 클래스가 많아서, 또는 소스코드를 사용할 수 없을 때 퍼사드 패턴을 사용한다. 이 패턴은 더 큰 시스템의 복잡성을 숨기고 클라이언트에 더 간단한 인터페이스를 제공한다. 일반적으로 클라이언트에 필요한 구성원 집합을 포함하는 단일 래퍼 클래스가 포함된다. 이 멤버는 Facade 클라이언트를 대신하여 시스템에 액세스하고 구현 세부 사항을 숨긴다

 

대충 소스코드가 복잡할 때 인터페이스 써서 만드는 패턴인 듯하다.

다른 포스팅에선 퍼사드 패턴을 어떻게 설명하는지 확인해보자.

 

  • 어떤 서브시스템의 인터페이스에 대한 통합된 인터페이스를 제공한다. 퍼사드에서 고수준의 인터페이스를 제공하기 때문에, 서브시스템을 더 쉽게 쓸 수 있다
  • 퍼사드 패턴은 어떤 소프트웨어의 다른 커다란 코드 부분에 대해 간략화된 인터페이스를 제공하는 디자인 패턴이다. 복잡한 소프트웨어 바깥에 있는 코드가 라이브러리의 내부 코드에 의존하는 정도를 낮춰 주고, 복잡한 소프트웨어를 쓸 수 있도록 간단한 인터페이스를 제공한다
  • 여러 메서드를 써서 하나의 단순한 기능을 수행하는 인터페이스를 만드는 패턴이다. 사용자가 객체의 여러 기능을 더 쉽게 사용할 수 있게 한다

세탁기, 건조기 등 가전제품을 예시로 생각할 수 있을 듯하다.

건조기를 예로 들면 나는 건조기에 빨래를 넣고 버튼만 누르면 된다. 패딩이면 패딩용, 이불이면 이불용 등등 필요하면 다른 옵션을 누르면 된다.

이 때 나는 건조기가 어떤 작동원리로 동작하는지 따위 알 필요 없다. 누르기 전에 매뉴얼을 보면서 작동원리를 이해해서 작동시켜야 한다면 그냥 자연건조 시키고 말지.

그래서 건조기 제조사들은 사람들이 단순한 버튼으로 건조기를 작동시킬 수 있도록 인터페이스를 제공한다.

 

말 나온 김에 건조기로 퍼사드 패턴의 예시를 들어보려고 한다. 건조기의 구성과 기능은 아래와 같다고 가정한다.

타이머 정해진 시간이 되면 건조기의 작동을 멈춘다
건조기 빨래를 건조시킨다
먼지받이 건조 과정에서 나오는 먼지를 모아둔다
회전통 통을 회전시킨다

 

일단 건조기를 켜야 하니까 건조기의 전원을 켜고 끄는 전원이 하나 있어야 할 것이다.

이 전원을 인터페이스로 만들면 아래 형태가 될 것이다.

 

// 전원
public interface PowerSupply
{
    public void on();
    public void off();
}

 

나머지 4개를 만든다면 아래처럼 만들 수 있다.

// 건조기
public class DryingMachine implements PowerSupply
{
    @Override
    public void on()
    {
        System.out.println("건조기 작동 시작...");
    }

    @Override
    public void off()
    {
        System.out.println("...건조기 작동 종료");
    }
}
// 먼지받이
public class DustAcceptor implements PowerSupply
{
    @Override
    public void on()
    {
        System.out.println("먼지받이 작동 시작...");
    }

    @Override
    public void off()
    {
        System.out.println("...먼지받이 작동 종료");
    }
}
// 회전통
public class Rumbler implements PowerSupply
{
    @Override
    public void on()
    {
        System.out.println("회전통 작동 시작...");
    }

    @Override
    public void off()
    {
        System.out.println("...회전통 작동 종료");
    }
}
// 타이머
public class MachineTimer implements PowerSupply
{
    public static long TIME_INTERVAL = 1000;
    private int finishTime;
    private Timer timer;
    private TimerTask task;
    int count = 0;
    MachineFacade facade;

    public MachineTimer(int sec, MachineFacade facade)
    {
        this.finishTime = sec;
        this.count = finishTime / 1000;
        this.facade = facade;
        timer = new Timer();
        this.facade = facade;
        task = new TimerTask()
        {
            @Override
            public void run()
            {
                if (count > 0)
                {
                    System.out.println("[Timer] " + (count--) + "초 남았습니다");
                }
                else
                {
                    System.out.println("[Timer] 건조가 완료되었습니다");
                    timer.cancel();
                    facade.off();
                }
            }
        };
    }

    @Override
    public void on()
    {
        timer.schedule(task, 0, TIME_INTERVAL);
    }

    @Override
    public void off()
    {
        timer.cancel();
    }
}

 

이제 이것들을 일일이 작동시키려면 클래스 객체를 만들어 on()을 모두 호출해야 한다.

이 때 퍼사드 패턴을 쓰면 건조기 버튼 한 번 누르는 것으로 건조기를 작동시킬 수 있다.

아래는 퍼사드 패턴을 적용한 클래스다.

 

public class MachineFacade
{
    DryingMachine dryingMachine;
    Rumbler rumbler;
    DustAcceptor dustAcceptor;
    MachineTimer timer;
    PowerSupply[] supplies;
    boolean isActive = false;

    public MachineFacade(DryingMachine dryingMachine, Rumbler rumbler, DustAcceptor dustAcceptor, MachineTimer timer)
    {
        this.dryingMachine = dryingMachine;
        this.rumbler = rumbler;
        this.dustAcceptor = dustAcceptor;
        this.timer = timer;
        supplies = new PowerSupply[]{dryingMachine, rumbler, dustAcceptor, timer};
    }

    public MachineFacade()
    {
        dustAcceptor = new DustAcceptor();
        rumbler = new Rumbler();
        dryingMachine = new DryingMachine();
        timer = new MachineTimer(3000, this);
        supplies = new PowerSupply[]{dryingMachine, rumbler, dustAcceptor, timer};
    }

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

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

}

 

이제 메인 클래스를 만들고 여기에 퍼사드 클래스의 객체를 만들어 on()만 호출하면 건조기가 작동하게 될 것이다.

 

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

 

메인의 결과는 아래와 같다.

 

 

건조기가 마지막에 종료돼야 하는데 순서가 좀 이상하지만 예제니까 넘어가자. 아무튼 이런식으로 on()을 한번 호출한것으로 다른 클래스의 on()들과 타이머를 시작시켜 건조기가 작동하는 것처럼 만들 수 있다.

 

주의할 것은 퍼사드 클래스가 서브 시스템 클래스들을 캡슐화하는 것은 아니다. 기능 편하게 쓰라고 인터페이스를 제공할 뿐이다.

반응형

'개인 공부 > 디자인 패턴' 카테고리의 다른 글

빌더(Builder) 패턴이란?  (0) 2022.01.02
팩토리 패턴이란?  (0) 2021.10.05
[MVVM] MutableLiveData와 LiveData 차이  (0) 2021.04.24
[Android] 관찰자(Observer) 패턴이란?  (0) 2021.04.11
MVC 패턴이란?  (0) 2020.11.27
Comments