어뎁터 패턴 & 파사드패턴
어뎁터 패턴 & 파사드패턴
어뎁터 패턴
C-type 충전기를 아이폰에 꽃아 충전을 하려면 C-type을 8-pin으로 바꿔주는 어뎁터 잭이 필요하다.
이처럼 어떤 클래스의 인터페이스를 클라이언트가 쓰고자하는 다른 인터페이스로 변환하여 호환성 문제를 해결하는것을 어뎁터 패턴이라고 한다.
같이 쓸수없는 클래스들을 같이 쓸수있도록 함
클라이언트나 어떤 클래스가 비슷한 구조의 여러 클래스를 사용해야 하지만 이 여러 클래스들이 각기 다른 인터페이스를 사용하는경우 어뎁터를 만들어 사용함
어뎁터 패턴 구조
클래스 어댑터는 보통 다중 상속을 이용하여 구현하기 때문에 자바에서는 사용할 수 없기 때문에 객체 어댑터로 설명한다.
아래 예제를 보고 나면 클래스 어댑터의 구조가 눈에 보일것이다.
하지만 자바에서도 adaptee를 상속받고 필요한 새 인터페이스를 제공하는 형태로 클래스 어댑터 형태로 구현 가능
클래스 어뎁터를 보면 상속으로 구현 but. 자바는 다중상속이 불가함
//Target or Adaptee public interface Duck { public void quack(); public void fly(); } public class MallardDuck implements Duck { @Override public void quack() { System.out.println("Quack"); } @Override public void fly() { System.out.println("flying"); } } //==================================================== //Target or Adaptee public interface Turkey { public void gobble(); public void fly(); } public class WildTurkey implements Turkey{ @Override public void gobble() { System.out.println("Gobble gobble"); } @Override public void fly() { System.out.println("I'm flying a short distance"); } }
이렇게 서로다른 인터페이스를 가진 구현 클래스 WildTurkey 와 MallardDuck이 있다.
클라이언트는 Turkey인터페이스를 Duck 인터페이스로 쓰고싶다.
Turkey인터페이스를 Duck 인터페이스로 변환하는 어뎁터를 만들어보자.
//어뎁터: Target: Duck , Adaptee: Turkey public class TurkeyAdapter implements Duck { Turkey turkey; //has-a Turkey interface: adaptee public TurkeyAdapter(Turkey turkey) { //Di concrete class this.turkey = turkey; } @Override public void quack(){ turkey.gobble(); //사용에 맞게 변환 } @Override public void fly() { turkey.fly(); //사용에 맞게 변환 } }
클라이언트
public class DuckTestDrive { public static void main(String[] args) { Duck duck = new MallardDuck(); //duck Turkey turkey = new WildTurkey(); //turkey Duck turkeyAdapter = new TurkeyAdapter(turkey); //turkey->duck use(duck); use(turkeyAdapter); } public static void use(Duck duck){ //Duck 인터페이스로 turkey 객체를 사용할수있다. duck.quack(); duck.fly(); } }
클라이언트는 Turkey인터페이스를 Duck 인터페이스로 쓸수있게 되었다.
어뎁터 종류
만능 어댑터: 한 클래스에 대한 여러 개의 다른 인터페이스를 제공하여 주는 adapter
두 방향 어댑터: 새 인터페이스(target)뿐만 아니라 기존 인터페이스(adaptee)도 함께 제공
public class TurkeyAdapter implements Duck, Turkey { //새 인터페이스 변환 //기존 인터페이스 사용 }
정리
장점 • 어댑터 클래스는 SRP에 충실한 클래스 • 어댑터는 OCP를 제공하는 한 가지 방법임. 기존 클래스를 수정하지 않고 서비스 제공
단점 • 경우에 따라 어댑터를 만들기보다 어댑티를 바꾸는 것이 간단할 수 있음. 보통 어댑티와 클라이언 트를 모두 수정하기 힘들거나 적절하지 않을 때 사용하는 패턴임
파사드 패턴
파사드 패턴 구조
왼쪽과 같이 클라이언트들이 시스템과 복잡한 의존관계를 맺고있을때 , 오른쪽 처럼 시스템의 복잡한 구조를 아우르는 상위타입 인터페이스를 파사드라고한다.
여러 종류의 파사드를 만들어 목적에 따라 제공할 수도 있음
복잡한 시스템에 대한 단순화된 인터페이스를 제공해야 할 때 사용한다.
시스템이 변경되더라도 클라이언트와 관계를 변경할 필요가 없고 파사드만 수정하면된다.
클라이언트가 내부 복잡한 로직을 몰라도 시스템을 쉽게 사용할수있도록 한다.
보통 싱글톤으로 구현된다.