어떤 소프트웨어 시스템에 새로운 업체에서 제공한 클래스 라이브러리를 사용해야 하는 상황인데, 해당 업체의 인터페이스가 기존의 인터페이스와 다르다면? 새로운 인터페이스를 기존에 사용하던 인터페이스에 적응시켜주는 Apaptor가 필요하다. Apaptor는 클라이언트의 요청을 받아서 새로운 업체에서 제공하는 클래스를 클라이언트가 받을 수 있는 형태로 변환해 주는 역할이다.
// Duck 인터페이스. 거위 객체들은 이를 상속
public interface Duck{
public void quack();
public void fly();
}
// Turkey 인터페이스. 칠면조 객체들은 이를 상속
public interface Turkey{
public void gobble();
public void fly();
}
위와 같이 거위와 칠면조의 인터페이스가 있다고 가정하자. 그런데, 거위의 객체 부족해서, 임시로 칠면조 객체를 사용해야 하는 상황이 발생했다. 상속받는 인터페이스가 완전히 다르기 때문에, 칠면조 객체를 바로 사용할 수는 없지만, 다음과 같이 Apaptor를 사용하여 문제를 해결할 수 있다.
public class TurkeyAdaptor implements Duck{ // 클라이언트에서 원하는 거위 인터페이스로 구현
Turkey turkey;
public TurkeyAdaptor(Turkey turkey){
this.turkey = turkey;
}
public void quack(){
turkey.quack();
}
public void fly(){
for(int i = 0 ; i < 5 ; i++){
// 거위만큼 오래 날지는 못함
turkry.fly()
}
}
}
특정 클래스 인터페이스를 클라이언트에서 요구하는 다른 인터페이스로 변환한다. 인터페이스가 호환되지 않아 같이 쓸 수 없었던 클래스를 사용할 수 있게 도와준다.
Adaptor Pattern을 사용하면 호환되지 않는 인터페이스를 사용하는 클라이언트를 Adaptor를 통해서, 별도의 수정없이 그대로 사용할 수 있다. 이는 클라이언트와 구현된 인터페이스를 분리할 수 있으며, 변경 내역이 Adaptor에 캡슐화되어 추후에 인터페이스가 변하더라도 클라이언트는 바꿀 필요가 없다는 장점이 있다.
초창기 Java에서 사용하던 인터페이스. 컬렉션의 항목이 어떻게 관리되는지 신경 쓸 필요 없이 모든 항목에 접근이 가능하다. hasMoreElements(), nextElement()매서드를 보유하고 있다.
최근 Java에서 사용하고 있는 인터페이스. Enumeration와 유사한 기능을 한다. hasNext(), next(), remove()매서드를 보유하고 있다.
Enumeration인터페이스를 Iterator인터페이스로 변환시킨다고 가정하자. Iterator에 있는 hasNext(), next()메서드들은 각각 Enumeration의 hasMoreElements(), nextElement()에 매핑되지만, remove()는 매핑되지 않는다. Enumeration가 읽기 전용 인터페이스이기 때문이다. 이러한 경우에는 exception을 통한 예외처리를 해주어야 한다.
서브 시스템에 있는 일련의 인터페이스를 통합 인터페이스로 묶어준다. 또한 고수준 인터페이스도 정의함으로 서브 시스템을 더 편리하게 사용할 수 있다.
Fasade Pattern을 사용하면 어떤 서브 시스템에 속한 일련의 복잡한 클래스를 단순하게 바꿔서 통합한 클래스를 만들 수 있다. 이러한 방식에는 클라이언트와 서브 시스템이 서로 긴밀하게 연결되지 않아도 된다는 장점이 있다.
예시를 들어보자. 가정용 영화관을 만드려고 한다. 일반적인 방식을 통해 구현하면, 영화를 볼때마다 팝콘 기계를 켜고, 조명을 조절하고, 스크린을 내리고, 영화를 고르고, 영화를 재생하는 등 너무 많은 일을 수행해야한다. 심지어 영화를 다 보면 이러한 과정을 그대로 역순으로 실행한다. Fasade Pattern을 통해서 이를 단순화 할 수 있다. Fasade Pattern의 주요한 용도는 단순화된 인터페이스를 통하여 서브 시스템을 더욱 간편하게 사용하는 것이다.
public class HomeTheaterFacade{
Amplifier amp;
Tuner tuner;
Projector projector;
Screen screen;
public HomeTheaterFacade(Amplifier amp, Tuner tuner, Projector projector, Screen screen){
this.amp = amp;
this.tuner = tuner;
this.projector = projector;
this.screen = screen;
// 기타 메서드
}
}