퍼사드 패턴이란, 사용하기 복잡한 라이브러리들을 사용하기 편리하도록 간편한 인터페이스를 구성하기위한 구조패턴이다
라이브러리의 클래스와 메서드의 동작을 바로 이해하기 어려워 사용하기 어려울때, 이에 대해서 적절한 네이밍과 정리를 통해 사용자들이 쉽게 하용할 수 있도록 인터페이스를 생성
이를 통해서 개발자의 실수를 방지할 수 있다
교제를 보고 이해하기 쉽도록 노트에 재정리하는 행위와 비슷
사용자는 간단하게 구성된 인터페이스를 사용해서 내부의 복잡한 시스템에 상관없이 기능을 사용 가능
Facade : 정면을 의미 -> 건축의 정면을 보고 건축의 목적을 바로 알 수 있음
그림에서 볼 수 있듯이 클라이언트는 Facade만 보고 기능을 사용하고 내부의 복잡한 로직을 신경쓰지 않는다.
위에 그림에서 보면 클라이언트가 Facade를 사용해서 내부 복잡한 시스템을 간다하게 사용하는데 사용되는 서브 클래스들은 또 다른 Facade 클래스가 될 수 있고 이렇게 만들어진 또 다른 Facade 패턴은 다시 다른 Facade에 의해 사용될 수 있다.
내부의 로직이 변경되어야 하는 상황이 생겨도 사용자는 Facade만 따르면 되기때문에 상관이 없어지고 의존성이 감소됩니다.
퍼사드 클래스가 모든 클래스에 결합된 GOD 객체가 될 수 있다
GOD(신) 객체
하나의 클래스의 여러 개의 책임이 있는 클래스
SOLID 5대원칙중 SRP원칙을 위반
퍼사드 객체는 서브 시스템에 대한 의존성을 갖게되어 의존성을 완전히 무시할 수는 없다
Facade 클래스를 설계하면 코드가 늘어나기 때문에 유지보수 비용이 더 많이 든다
- 때문에 Facade를 추가해서 얻게되는 이점과 추가적인 유지보수 비용을 비교하여 결정
DB관련 라이브러리를 사용하는 코드가 main에 그대로 작성된 코드
class Client {
public static void main(String[] args) {
// 1. 데이터베이스 생성 & 등록
DBMS dbms = new DBMS();
dbms.put("홍길동", new Row("홍길동", "1890-02-14", "honggildong@naver.com"));
dbms.put("임꺽정", new Row("임꺽정", "1820-11-02", "imgguckjong@naver.com"));
dbms.put("주몽", new Row("주몽", "710-08-27", "jumong@naver.com"));
// 2. 캐시 생성
Cache cache = new Cache();
// 3. 트랜잭션에 앞서 먼저 캐시에 데이터가 있는지 조회
String name = "홍길동";
Row row = cache.get(name);
// 4. 만약 캐시에 없다면
if (row == null){
row = dbms.query(name); // DB에 해당 데이터를 조회해서 row에 저장하고
if(row != null) {
cache.put(row); // 캐시에 저장
}
}
// 5. dbms.query(name)에서 조회된 값이 있으면
if(row != null) {
Message message = new Message(row);
System.out.println(message.makeName());
System.out.println(message.makeBirthday());
System.out.println(message.makeEmail());
}
// 6. 조회된 값이 없으면
else {
System.out.println(name + " 가 데이터베이스에 존재하지 않습니다.");
}
}
}
Facade 객체를 통해서 간단하게 사용할 수 있는 인터페이스 제공
class Facade {
private DBMS dbms = new DBMS();
private Cache cache = new Cache();
public void insert() {
dbms.put("홍길동", new Row("홍길동", "1890-02-14", "honggildong@naver.com"));
dbms.put("임꺽정", new Row("임꺽정", "1820-11-02", "imgguckjong@naver.com"));
dbms.put("주몽", new Row("주몽", "710-08-27", "jumong@naver.com"));
}
public void run(String name) {
Row row = cache.get(name);
// 1. 만약 캐시에 없다면
if (row == null){
row = dbms.query(name); // DB에 해당 데이터를 조회해서 row에 저장하고
if(row != null) {
cache.put(row); // 캐시에 저장
}
}
// 2. dbms.query(name)에서 조회된 값이 있으면
if(row != null) {
Message message = new Message(row);
System.out.println(message.makeName());
System.out.println(message.makeBirthday());
System.out.println(message.makeEmail());
}
// 3. 조회된 값이 없으면
else {
System.out.println(name + " 가 데이터베이스에 존재하지 않습니다.");
}
}
}
class Client {
public static void main(String[] args) {
// 1. 퍼사드 객체 생성
Facade facade = new Facade();
// 2. db 값 insert
facade.insert();
// 3. 퍼사드로 데이터베이스 & 캐싱 & 메세징 로직을 한번에 조회
String name = "홍길동";
facade.run(name);
}
}
중요한점은 Facade를 구성하는 기능을 적게 구성하는 것이다. 만약 Facade를 구성하는 기능들이 많아진다면 사용자는 똑같은 복잡함을 느끼게 될 것이다.