Adapter Pattern

김영우 (AvocadoSmasher)·2022년 12월 5일
0

Design Pattern

목록 보기
8/8

🔎 What is Adapter Pattern??

어댑터 패턴(Adapter Pattern)은 호환이 되지 않는 두개의 객체를 서로 호환할 수 있도록 하는 중간의 Converter같은 존재의 패턴입니다. 이러한 어댑터 패턴은 One-way로 제작할수도 있고 Two-way로 제작할수도 있습니다.

조금 더 쉬운 이해를 위해 여러분들이 사용하시는 어댑터를 생각하시면 될것같은데 실생활에서 어댑터를 어떤 경우에 사용하시나요? 저는 주로 USB 를 제 휴대폰에 꽂을때 사용하거나 USB를 C-Type 포트에 꽂아 사용하기 위해 사용하는데 어댑터 패턴도 이와 같은 성질을 가지는 디자인 패턴입니다. 표준이 서로 맞지 않아서 호환되지 않는 두 객체를 서로 호환할 수 있는 형태로 맞춰서 호환이 가능하게 해주는 형태입니다.

⚓️ Digging into how it works

프로그래밍? 적인 관점에서 본다면 예를들어 웹페이지를 제작한다고 생각해봅시다. 당신은 지금 서버로부터 데이터를 받아서 그래프를 그리는 페이지를 제작하려 합니다. 서버로부터 JSON 형태의 데이터를 받을 수 있습니다. 여기까지 좋습니다. 그럼 이제 그래프에 해당 데이터를 표현해야하는데 그래프를 그리는 것이 생각보다 어려워 외부 라이브러리를 사용해 그래프로 표현하려 하는데 해당 라이브러리는 데이터 파일을 받아 자동으로 그래프화 해주는 API를 제공합니다. 너무 좋은 라이브러리인데… 어라? JSON의 형태의 데이터가 아니라 XML 형태의 데이터를 받는다고 하네요… 이럴때 어떻게 해야할까요? 이때 어댑터 패턴을 적용하시면 됩니다. JSON 데이터를 넘겨주면 이를 XML 데이터로 바꿔주는 어댑터를 만드는 겁니다. 그렇게 되면 JSON 데이터로 그래프를 그릴 수 있게 되는거지요. 마치 USB를 C-type 포트에 꽂아서 사용하듯 말이지요.

제가 안드로이드 앱 프로그래밍을 할 당시에 ListView를 사용할때 Adapter를 사용했었습니다. 그때 당시에는 디자인 패턴이라는게 있다. 라는 정도만 인지하고 있었어서 그냥 “어댑터를 쓰면 ListView에 데이터를 표현할 수 있다.” 라고만 알고있었는데 이렇게 디자인 패턴을 공부하면서 다시보니 감회가 새로워서 재미있네요.

당시 Adapter를 사용할때 ListView에 데이터를 표현하기 위해 BaseAdapter를 실체화 하여 CustomAdapter르르 만들고 그 안에서 getCount(), getItem() 등과 같은 메소드를 Override 하여 구현하고 Adapter에 ArrayList형태의 데이터를 넘겨 구현하고 생성한 뒤 ListView의 setAdapter() 메소드를 통해 생성한 Adapter를 넘겨주었던 기억이 있는데 이게 Adapter Pattern을 적용한 사례가 될 수 있을것 같네요.

이를 간단하게 클래스 다이어그램으로 표현을 하자면 다음과 같습니다.

💻 Code (feat. Java)

상상력을 발휘해 봅시다. 현재는 C-type 케이블이 있죠? 과거로 돌아가 핀이 5개 있는 A-type이라는 케이블을 사용하다가 이제 B-type이라는 핀이 3개 있는 새로운 타입의 케이블이 유행하기 시작했다고 해봅시다.(요즘의 발전은 추가가 아니라 최소화 하는게 트랜드인것 같으니 5핀에서 3핀으로 변화했다고 합시다.)

여러분은 지금 A-type 케이블을 B-type으로 호환하는 어댑터를 디자인 해야하고 고객은 그냥 단순히 useDevice()라는 메소드를 통해서 케이블을 사용하고 기존의 A-type 케이블의 첫번째 두번째 핀이 B-type의 첫번째, 세번째 네번째 핀이 B-type의 두번째, 다섯번째 핀이 B-type의 세번째 핀에 호환이 되도록 디자인을 해야합니다. 어떻게 해야할까요?

Adapter Pattern을 사용하면 다음과 같이 표현 가능합니다.

public class Client{
		Btype cable;
		public void useDevice(){
				cable.use();
		}
}
public interface Atype {
		public void use();
		public String getDataFromPin1();
		public String getDataFromPin2();
		public String getDataFromPin3();
		public String getDataFromPin4();
		public String getDataFromPin5();
}
public interface Btype{
		public void use();
		public String getDataFromPin1();
		public String getDataFromPin2();
		public String getDataFromPin3();
}

이와 같은 형태라고 심플하게 생각합시다. 이때 Atype에서 Btype으로 가는Adapter를 만든다면 다음과 같습니다.

public class AtoB_Adapter implements Btype{
		Atype cable;
		public AtoB_Adapter(Atype cable){
				this.cable = cable;
		}
		@Override
		public String getDataFromPin1(){
				String data = cable.getDataFromPin1() + cable.getDataFromPin2();
				return data;
		}
		@Override
		public String getDataFromPin2(){
				String data = cable.getDataFromPin3() + cable.getDataFromPin4();
				return data;
		}		
		@Override
		public String getDataFromPin3(){
				return cable.getDataFromPin5();
		}
		@Override
		public void use(){
				System.out.println("Data From Pin1 : " + getDataFromPin1());
				System.out.println("Data From Pin2 : " + getDataFromPin2());
				System.out.println("Data From Pin3 : " + getDataFromPin3());
		}
}

📌 Summary

오늘은 Adapter Pattern에 대해 알아보았습니다. Adapter Pattern은 서로 호환되지 않는 인터페이스를 호환될 수 있도록 Adapter라는 중간의 클래스를 만들어서 Target(내가 실제로 사용하고자 하는 객체의 인터페이스) 인터페이스를 Adapter class가 실체화 하고 Adaptee(Target으로 호환되도록 하고싶은 인터페이스)를 실체화한 객체를 받아 Target 인터페이스의 입맛대로 Adaptee의 데이터를 활용할 수 있도록 하는 패턴이었습니다.

예시로 들은 코드가 사실 완전히 적절하진 않다는 것을 어느정도 인지하고 있습니다.(사실 애초에 Cable이라는 형태의 인터페이스를 만들고 이를 실체화한 각 타입의 케이블을 만들어 표준화 하면 해결…) 그럼에도 불구하고 해당 예시를 든 이유는 바로 생각난 예시가 저것이라… 그렇습니다. 그래도 최대한 Adapter Pattern 스럽게 구성을 해보았으니 너그럽게 용서해 주시면 감사하겠습니다.

profile
Android Studio 공부 중

0개의 댓글