퍼사드 패턴
여러 개의 서브 시스템이나 복잡한 클래스들을 간단한 인터페이스를 통해 외부로 노출시키는 패턴. 클라이언트에게 획일화된 하나의 인터페이스를 제공함으로써, 클라이언트는 복잡합 동작 과정을 알 필요가 없이 인터페이스의 기능을 사용할 수 있다.
구조
기본 인터페이스
//서브시스템 클래스
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 같은 클래스에 대해 전혀 모르는 상태이지만, 퍼사드 클래스에서 해당 클래스간의 연계, 복잡성 등을 숨기고 실행함으로써 클라이언트에게 더 간단한 방식으로 똑같은 서비스를 제공할 수 있다.
장점
- 사용자에게 간단한 인터페이스만 제공할 수 있다.
- 하위 시스템 간의 의존관계가 많은 경우 퍼사드 패턴에 의존성을 집중시킬 수 있다.
- 시스템의 동작을 계층화할 수 있다.
단점
- 모든 클래스와 결합된 전지전능한 클래스가 될 수 있다.
- 퍼사드 클래스 자체가 서브 클래스에 대해 의존성을 갖게 된다.
- 유지보수 자체가 해결되지 않았다. 퍼사드 패턴을 확장해야 할 경우 의존성 관계 때문에 유지보수가 힘들어질 수 있다.
전체 예시 코드
// 퍼사드 클래스
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
참고자료
'프로그래밍 이론 > 디자인 패턴' 카테고리의 다른 글
12. [Design Pattern] 프록시(Proxy) 패턴 (1) | 2024.01.06 |
---|---|
11. [Design Pattern] 플라이웨이트(Flyweight) 패턴 (0) | 2023.12.27 |
09. [Design Pattern] 데코레이터(Decorator) 패턴 (1) | 2023.12.10 |
08. [Design Pattern] 컴포지트(Composite) 패턴 (1) | 2023.11.25 |
07. [Design Pattern] 브릿지(Bridge) 패턴 (0) | 2023.11.23 |