Contents
Adapter (어댑터)Adapter (어댑터)
- Proxy와 별개로 해당 객체의 다른 책임을 대신 받아서 처리할 수 있는 객체
- 기존 시스템의 구조를 해치지 않으면서 새 클래스를 기존 시스템에 넣을 수 있도록 변환


어댑터는 책임을 위임 받는 역할이 아님
- 어댑터는 새로운 기능이 추가되어야 할 때 기존 시스템에 맞춰서 끼우기 위한 도구
- 프록시처럼 역할을 위임받는 역할이 아니지만 SRP, DIP를 수행하기 위해 비슷한 역할을 수행할 수 있음
Q1. 동물의 객체 이름이 name이 아닌 fullName으로 왔다면?
- 동물 객체는 name을 이용한 getName을 사용
- OuterTiger는 fullName을 사용하므로 메소드를 맞추어줘야 하는데, 이를 직접 건드리면 안됨
- 다른 곳에서 메소드를 사용 중일 경우 모든 곳을 손봐야 함
// 외부 요소
public class OuterTiger {
private String fullName = "호랑이";
public String getFullName() {
return fullName;
}
}
A : 기존 동물 객체에서 사용하던 name으로 맞춰주는 어댑터가 필요함
// Adapter : Animal 객체에 OuterTiger를 맞추기 위한 수단
public class TigerAdapter extends Animal{
// DI
private OuterTiger outerTiger;
public TigerAdapter(OuterTiger outerTiger) {
this.outerTiger = outerTiger;
}
// extends
@Override
String getName() {
return outerTiger.getFullName();
}
}
public class App {
public static void main(String[] args) {
Mouse m1 = new Mouse();
Doorman d1 = new Doorman();
Cat c1 = new Cat();
// 기존 코드는 놔두면서 어댑터만 추가함
TigerAdapter ta = new TigerAdapter(new OuterTiger());
d1.쫓아내(m1);
d1.쫓아내(c1);
d1.쫓아내(ta);
}
}
Q2. 로그인 방법을 하나 더 추가할 건데, 코드를 건드리지 않으려면?
- 카카오, 구글 로그인이 구현되어 있음
- 페이스북 로그인을 추가할 건데, 로그인 하면 uid, uname을 리턴함
A :
내가 푼 답
- 로그인 하는 provider에 따라 로그인을 구분해야 하는데, AuthAdapter에서 이를 처리하도록 수정
- Authenticator의 책임이 너무 많으므로 추상화
- provider → loginadapter → authadapter → kakao, google, facebook으로 분할
Feedback :
- provider에 따라 로그인을 구분할 때는 해당하는 provider를 선택해주는 factory가 필요
- factory가 있으면 loginadapter, authadapter가 필요 없어짐
- 카카오, 구글, 페이스북 프로필 정보를 가져오는 UserProfile 객체가 필요
- 추상화로 구성하여 단일 객체에만 의존하도록 수정
- 이때, 카카오, 구글, 페이스북 프로필이 전부 UserProfile에 상속되어 있어야 함
- 카카오, 구글, 페이스북 로그인의 책임을 각자 상속받는 객체들이 필요
- Authentication은 내부 구조는 필요 없음 (추상 클래스만)
풀이
- App.java
// FacebookProfile -> uId, uName (이게 추가될때 기존 코드를 손되지 않을 수 있게 하는게 목표)
public class App {
static void mainPage(UserProfile profile) {
System.out.println("로그인 하신 아이디는 " + profile.getUsername() + " 입니다.");
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String provider = sc.nextLine();
// 객체 생성 전담 클래스를 만들어서 처리해주면 좋다.
Authentication authentication;
if (provider.equals("google")) {
authentication = new GoogleAuthentication();
} else if (provider.equals("kakao")) {
authentication = new KakaoAuthentication();
} else if (provider.equals("facebook")) {
authentication = new FacebookAuthentication();
} else {
System.out.println("지원하지 않는 Provider 입니다.");
return;
}
UserProfile userProfile = authentication.login();
mainPage(userProfile);
}
}
- Authentication.java
public abstract class Authentication {
public abstract UserProfile login();
}
- UserProfile.java
// 추상화
public class UserProfile {
public int getId() {
return 0;
}
public String getUsername() {
return "정원";
}
}
- FacebookAuthentication.java
// SRP를 지키기 위해
public class FacebookAuthentication extends Authentication {
public UserProfile login() {
System.out.println("페이스북 로그인 완료");
return new FacebookProfile(999, "love");
}
}
- GoogleAuthentication.java
// SRP를 지키기 위해
public class GoogleAuthentication extends Authentication {
public UserProfile login() {
System.out.println("구글 로그인 완료");
return new GoogleProfile(500, "cos");
}
}
- KakaoAuthentication.java
// SRP를 지키기 위해
public class KakaoAuthentication extends Authentication {
public UserProfile login() {
System.out.println("카카오 로그인 완료");
return new KakaoProfile(1, "ssar");
}
}
- FacebookProfile.java
public class FacebookProfile extends UserProfile {
private int uId;
private String uName;
public FacebookProfile(int uId, String uName) {
this.uId = uId;
this.uName = uName;
}
public int getId() {
return uId;
}
public String getUsername() {
return uName;
}
}
- GoogleProfile.java
public class GoogleProfile extends UserProfile {
private int id;
private String username;
public GoogleProfile(int id, String username) {
this.id = id;
this.username = username;
}
public int getId() {
return id;
}
public String getUsername() {
return username;
}
}
- KakaoProfile.java
public class KakaoProfile extends UserProfile {
private int sub;
private String name;
public KakaoProfile(int sub, String name) {
this.sub = sub;
this.name = name;
}
public int getId() {
return sub;
}
public String getUsername() {
return name;
}
}
Q3. 미연결된 네이버 로그인도 연결하려면?
A :
- 네이버 프로필에서 id와 mainName을 반환 (UserProfile의 getId, getUsername을 사용할 수 없음)
- 네이버 프로필 어댑터 생성 (id, mainName을 받아 getId, getUsername 구현)
- 네이버 로그인 인증 구현 (네이버 프로필 어댑터 타입 반환)
- main에서 인증 코드 삽입
Share article