어댑터 패턴이란?
💡 서로 호환되지 않는 인터페이스를 가진 객체들이 상호작용할 수 있도록 두 객체 사이에서 호환을 해주는 구조를 만드는 것입니다.
어댑터 패턴을 어떤 경우에 사용할까?
A 인터페이스를 사용하고 싶은데, A 타입의 데이터로만 작동한다. 하지만 나는 B 타입의 데이터를 입력받아 사용해야할 때
→ 궁여지책으로 A 인터페이스를 내가 원하는 B타입으로 작동하도록 수정할 수도 있지만, 그렇게 한다면 A 인터페이스에 의존하는 코드들을 수정해줘야한다. 또한, A 쪽의 코드에 내가 접근하지 못하는 경우라면, 이 해결방식조차 이용할 수 없다.
어댑터 패턴을 사용한다면?
- 클라이언트 코드와 사용하고자하는 코드의 수정 없이 호환 가능한 구조를 만들 수 있다.
- → OCP
- 타입을 변환해주는 로직을 분리할 수 있다. → 책임을 분리 → SRP
어댑터 패턴을 구현하는 방식
중요한 부분
- 어댑터는 클라이언트의 인터페이스를 따라야하고, 클라이언트도 인터페이스를 이용해서 어댑터를 사용해야한다. 그래야 추가적인 코드의 수정이 없기 때문!
- 어댑터는 데이터의 변환 책임만 갖도록 하자.
독수리를 닭으로 바꿔보겠습니다.
public interface Eagle { public void flyHigh(); public void eatMeat(); }
public class BaldEagle implements Eagle { public void flyHigh() { System.out.println("하늘 높이 날아갑니다."); } public void eatMeat() { System.out.println("고기를 먹습니다."); } }
public interface Chicken { public void flyLow(); public void eatFeed(); }
public class CornishChicken implements Chicken { public void flyLow() { System.out.println("높이 날지 못합니다."); } public void eatFeed() { System.out.println("사료를 먹습니다."); } }
public class EagleToChickenAdaptor implements Eagle { Chicken chicken; public ChickenAdaptor(Chicken chicken) { this.chicken = chicken; } public void flyHigh() { chicken.flyLow(); } public void eatMeat() { chicken.eatFeed(); } }
pubilc class App { public static void main(String[] args) { Eagle eagle = new BaldEagle(); System.out.println("독수리입니다."); eagle.flyHigh(); eagle.eatMeat(); System.out.println("-------------------"); EagleToChicken adaptor = new EagleToChicken(); System.out.println("닭이 된 독수리입니다."); adaptor.flyHigh(); adaptor.eatMeat(); System.out.println("-------------------"); Chicken chicken = new CornishChicken(); System.out.println("닭입니다."); chicken.flyLow(); chichen.eatFeed(); } }
💡 결과
독수리입니다.
하늘 높이 날아갑니다.
고기를 먹습니다.
-------------------
닭이 된 독수리입니다.
높이 날지 못합니다.
사료를 먹습니다.
-------------------
닭입니다.
높이 날지 못합니다.
사료를 먹습니다.