Adapter Pattern
View all Design Patterns
객체를 래핑(wrapping)하여 타 클래스와 호환이 가능하도록 하는 방법이다.
Class Diagram
Abstract overview
이때, Service
코드에는 타사 코드 등 변경할 수 없는 기존 레거시 코드가 포함된다.
Concrete example
이를 보면, 각각의 인증 방식(Naver, Google, Apple, Kakao)에 맞는 클래스를 각각의 어뎁터가 연관 관계(Aggregation)로 의존하고 있는 것을 알 수 있다. 또한 클라이언트는 AuthInterface
만 의존하게 되기 때문에, 추가적인 인증 방식이 필요한 경우 해당 클래스와 어뎁터를 추가하면 된다.
Code
interface AuthInterface {
authenticate(): void;
getUserDetails(): void;
}
class NaverAuthAdapter implements AuthInterface {
private naverAuth: NaverAuth;
constructor(naverAuth: NaverAuth) {
this.naverAuth = naverAuth;
}
authenticate(): void {
this.naverAuth.authenticateWithNaver();
}
getUserDetails(): void {
this.naverAuth.getUser();
}
}
class GoogleAuthAdapter implements AuthInterface {
private googleAuth: GoogleAuth;
constructor(googleAuth: GoogleAuth) {
this.googleAuth = googleAuth;
}
authenticate(): void {
this.googleAuth.authenticateWithGoogle();
}
getUserDetails(): void {
this.googleAuth.getUser();
}
}
class AppleAuthAdapter implements AuthInterface {
private appleAuth: AppleAuth;
constructor(appleAuth: AppleAuth) {
this.appleAuth = appleAuth;
}
authenticate(): void {
this.appleAuth.authenticateWithApple();
}
getUserDetails(): void {
this.appleAuth.getUser();
}
}
class KakaoAuthAdapter implements AuthInterface {
private kakaoAuth: KakaoAuth;
constructor(kakaoAuth: KakaoAuth) {
this.kakaoAuth = kakaoAuth;
}
authenticate(): void {
this.kakaoAuth.authenticateWithKakao();
}
getUserDetails(): void {
this.kakaoAuth.getUser();
}
}
class NaverAuth {
/**
* Naver의 인증 로직 사용
*/
authenticateWithNaver() {
console.log("Authenticated by Naver");
}
getUser() {
console.log("Fetched Naver user");
}
}
class GoogleAuth {
/**
* Google의 인증 로직 사용
*/
authenticateWithGoogle() {
console.log("Authenticated by Google");
}
getUser() {
console.log("Fetched Google user");
}
}
class AppleAuth {
/**
* Apple의 인증 로직 사용
*/
authenticateWithApple() {
console.log("Authenticated by Apple");
}
getUser() {
console.log("Fetched Apple user");
}
}
class KakaoAuth {
/**
* Kakao의 인증 로직 사용
*/
authenticateWithKakao() {
console.log("Authenticated by Kakao");
}
getUser() {
console.log("Fetched Kakao user");
}
}
const googleAuth = new GoogleAuth();
const googleAdapter = new GoogleAuthAdapter(googleAuth);
googleAdapter.authenticate(); // Authenticated by Google
googleAdapter.getUserDetails(); // Fetched Google user
// ...
Pros and Cons
Pros
- 타사 코드 등 변경할 수 없는 서비스 코드가 기존 코드에 영향을 주지 않으면서 사용이 가능하다.
- 비즈니스 로직과 어뎁터 로직을 분리함으로써 SRP(Single Responsibility Principle, 단일책임원칙)를 준수한다.
- 기존 코드(서비스 코드)의 재사용성이 향상된다.
Cons
- 여러 인터페이스와 클래스를 생성해야 하기 떄문에, 코드의 복잡성이 커진다.
- 기존 코드(서비스 코드)를 변경하는 것이 더 간단할 수 있다.