퍼사드 패턴?
- 퍼사드 패턴은 여러 인터페이스의 사용을 단순하게 만들어주는 패턴이다
다시 말해, 인터페이스를 통합하여 사용하기 쉬운 인터페이스를 제공하고 복잡한 시스템을 훨씬 편리하게 사용하도록 만들어준다.
예를 들어, 어떤 한 유저(User)가 영화를 보기 위하여 준비하는 과정을 생각해보자. 유저는 과자(Snach)를 준비하고, 음료(Beverage)를 준비하고, TV를 켜고, 볼 영화(Movie)를 찾고, 결제하고, 재생한다. 이 과정을 코드로 만들어 본다.
//Snack 클래스 class Snack { //Snack이름을 담을 변수 private String name; //Snack 생성자 public Snack(String name) { this.name = name; } //Snack 준비하기 메서드 public void prepare() { System.out.println(name + " Preparing"); } } //Beverage 클래스 class Beverage { //Beverage 이름을 담을 변수 private String name; //Beverage 생성자 public Beverage(String name) { this.name = name; } //Beverage 준비하기 메서드 public void prepare() { System.out.println(name + " Preparing"); } } //TV클래스 class TV { //TV를 키는 메서드 public void turnOn() { System.out.println("TV On!"); } } //Movie 클래스 class Movie { //Movie 이름을 담을 변수 private String name; //Movie 생성자 public Movie(String name) { this.name = name; } //Movie를 찾는 메서드 public void searchMovie() { System.out.println(name + " Searching!"); } //Movie를 결제하는 메서드 public void chargeMovie() { System.out.println("Charge For Movie " + name); } //Movie를 재생하는 메서드 public void playMovie() { System.out.println(name +" Play"); } } //User 클래스(main 클래스) public class User { public static void main(String[] args) { //Snack객체 생성 Snack snack = new Snack("눈을 감자"); //Beverage객체 생성 Beverage beverage = new Beverage("게토레이"); //TV객체 생성 TV tv = new TV(); //Movie객체 생성 Movie movie = new Movie("해리포터"); //Snack 준비 snack.prepare(); //Beverage 준비 beverage.prepare(); //TV 켜기 tv.turnOn(); //Movie 찾기 movie.searchMovie(); //Movie 결제하기 movie.chargeMovie(); //Movie 재생하기 movie.playMovie(); } } //결과값 눈을 감자 Preparing 게토레이 Preparing TV On! 해리포터 Searching! Charge For Movie 해리포터 해리포터 Play
만약 과정이 더 들어난다면, User클래스(main)에는 더 많은 객체를 생성해야하며, 코드는 끝도없이 길어지게 된다. 이를 보완하기 위한 패턴이 바로 퍼사드 패턴이다
- 기존 코드에 Facad클래스 추가하기
//Snack 클래스 class Snack { //Snack이름을 담을 변수 private String name; //Snack 생성자 public Snack(String name) { this.name = name; } //Snack 준비하기 메서드 public void prepare() { System.out.println(name + " Preparing"); } } //Beverage 클래스 class Beverage { //Beverage 이름을 담을 변수 private String name; //Beverage 생성자 public Beverage(String name) { this.name = name; } //Beverage 준비하기 메서드 public void prepare() { System.out.println(name + " Preparing"); } } //TV클래스 class TV { //TV를 키는 메서드 public void turnOn() { System.out.println("TV On!"); } } //Movie 클래스 class Movie { //Movie 이름을 담을 변수 private String name; //Movie 생성자 public Movie(String name) { this.name = name; } //Movie를 찾는 메서드 public void searchMovie() { System.out.println(name + " Searching!"); } //Movie를 결제하는 메서드 public void chargeMovie() { System.out.println("Charge For Movie " + name); } //Movie를 재생하는 메서드 public void playMovie() { System.out.println(name +" Play"); } } //Facade 클래스 정의 class Facade { //각 객체의 이름을 담을 변수 선언 private String snackName; private String beverageName; private String movieName; //Facade 생성자 public Facade(String snackName, String beverageName, String movieName) { this.snackName = snackName; this.beverageName = beverageName; this.movieName = movieName; } //한 메서드로 통합(=메서드 안에서 각 객체 생성) public void watchMovie() { Snack snack = new Snack(snackName); Beverage beverage = new Beverage(beverageName); TV tv = new TV(); Movie movie = new Movie(movieName); beverage.prepare(); tv.turnOn(); movie.searchMovie(); movie.chargeMovie(); movie.playMovie(); } } //User 클래스(main 클래스) public class User { public static void main(String[] args) { //Facade 객체 생성 Facade facade = new Facade("눈을 감자","게토레이","해리포터"); //메서드 실행 facade.watchMovie(); } } //결과값 게토레이 Preparing TV On! 해리포터 Searching! Charge For Movie 해리포터 해리포터 Play
장점
- 서브시스템들의 복잡성으로부터 코드를 분리할 수 있다(서브시스템들 사이의 결합도를 낮출 수 있다)
- 클라이언트들이 어떠한 기능을 위해 컨트롤해야 하는 객체의 수를 줄여준다(서브시스템으로부터 클라이언트를 보호하고, 클라이언트가 서브시스템을 사용하기 쉽게 해준다)
- 추상화를 통한 간결한 코드구현이 가능하다.
단점
- 퍼사드 클래스 안에 있는 통합된 인터페이스 중 하나라도 변경되면 오류가 발생할 수 있다.
- 이를 사용한 시스템은 모든 클래스에 결합된 객체가 될 수 있다(결합도가 높아진다)
- 클라이언트가 내부 서브시스템에 접근하는 것을 막기 어렵다.