[디자인 패턴] 어댑터(Adapter) 패턴
❓어댑터 패턴?
어댑터 패턴은 구조 패턴으로, 다른 말로 래퍼(Wrapper) 패턴이라고도 합니다. 연관성 없는 2개의 객체를 묶어서 인터페이스를 만들어 주는 패턴을 말하는데요, 이를 통해 서로 연관 없는 두 객체의 호환성을 이루어줄 수 있습니다!
❓어댑터 패턴의 종류
어댑터 패턴은 두 가지 방식이 있는데요, 클래스를 이용한 클래스 어댑터 패턴(Class Adapter Pattern), 그리고 객체를 이용한 객체 어댑터 패턴(Object Adapter Pattern)이 있습니다!
❗클래스 어댑터 패턴
클래스의 상속을 이용한 어댑터 패턴입니다.
// 기존에 사용하던 클래스
class OldDate {
constructor(dateString) {
this.dateString = dateString;
}
getFormattedDate() {
return this.dateString;
}
}
// 새로운 타겟 인터페이스
class NewDate {
constructor(date) {
this.date = date;
}
getFormattedDate() {
const year = this.date.getFullYear();
const month = this.date.getMonth() + 1;
const day = this.date.getDate();
return `${year}-${month}-${day}`;
}
}
// 어댑터 클래스
class DateAdapter extends NewDate {
constructor(oldDate) {
// 기존 클래스의 데이터를 새로운 클래스에 맞게 변환
const [year, month, day] = oldDate.getFormattedDate().split('-');
const newDate = new Date(year, month - 1, day);
// 새로운 클래스의 생성자 호출
super(newDate);
}
}
// 기존의 OldDate를 사용하는 경우
const oldDate = new OldDate('2023-11-14');
console.log(date.getFormattedDate()); // 2023-11-14
// 어댑터를 사용하여 NewDate 인터페이스로 호출
const adaptedDate = new DateAdapter(oldDate);
console.log(date.getFormattedDate()) // 2023-11-14
기존에 사용하던 OldDate 클래스를 NewData로 변경하려고 합니다. 이 때 기존의 데이터를 그대로 둔 채, 어댑터 클래스를 이용하여 원하는 형태를 만들 수 있고, 이를 통해 호환성을 가진 NewDate 클래스를 사용할 수 있게 됩니다.
하지만 상속을 이용하기 때문에 계층 간의 강한 결합이 생긴다는 단점이 있기 때문입니다.
❗객체 어댑터 패턴
객체의 의존성을 이용한 어댑터 패턴입니다.
// 기존에 존재하는 클래스
class OldDate {
constructor(dateString) {
this.dateString = dateString;
}
getFormattedDate() {
return this.dateString;
}
}
// 새로운 타겟 인터페이스
class NewDate {
constructor(date) {
this.date = date;
}
getFormattedDate() {
const year = this.date.getFullYear();
const month = this.date.getMonth() + 1;
const day = this.date.getDate();
return `${year}-${month}-${day}`;
}
}
// 어댑터 클래스
class DateAdapter {
constructor(oldDate) {
this.oldDate = oldDate;
}
getFormattedDate() {
// 기존 클래스의 데이터를 새로운 클래스에 맞게 변환
const [year, month, day] = this.oldDate.getFormattedDate().split('-');
const newDate = new Date(year, month - 1, day);
const adaptedDate = new NewDate(newDate);
return adaptedDate.getFormattedDate();
}
}
// 기존의 OldDate를 사용하는 경우
const oldDate = new OldDate('2023-11-14');
console.log(date.getFormattedDate()); // 2023-11-14
// 어댑터를 사용하여 NewDate 인터페이스로 호출
const adaptedDate = new DateAdapter(oldDate);
console.log(date.getFormattedDate()) // 2023-11-14
객체의 구성(Composition), 의존성을 이용하여 상속 없이 NewDate객체를 만들어낼 수 있습니다. 상속의 강한 결합이라는 단점을 해결한 방식이라는 것을 알게 되었네요!
❗결론!
어댑터 패턴은 코드의 성능이 향상되는 것이 아닙니다. 기존 코드와 호환성을 만들어낸다는 장점 때문에 사용하는 것이죠. 외부 라이브러리나 서드파티 컴포넌트에 사용하기 적합한 패턴이라고 할 수 있습니다. 성능은 오히려 어댑터가 생김으로써 속도가 저하됩니다. 그렇기 때문에 이를 유의하고 적절하게 사용하면 될 것 같습니다!