Skip to content

어댑터 패턴은 클래스의 인터페이스를 사용자가 기대하는 다른 인터페이스로 변환하는 패턴이다. 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 사용하는 것이기 때문에 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다는 장점이 있다.


예시 코드

public interface UserDetails {
String getUsername();
String getPassword();
}
public interface UserDetailsService {
UserDetails loadUser(String username);
}
public class LoginHandler {
private final UserDetailsService userDetailsService;
public LoginHandler(UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
}
public String login(String username, String password){
UserDetails userDetails = userDetailsService.loadUser(username);
if(userDetails.getPassword().equals(password)){
return userDetails.getUsername();
} else {
throw new RuntimeException();
}
}
}

UserDetails, UserDetailsService, LoginHandler는 security 패키지에서 제공하는 코드로 라이브러리 코드라고 생각해도 된다. 실습을 위해 간단히 구현한 코드이다.


@Data
public class Account {
private String name;
private String password;
private String email;
}
public class AccountService {
public Account findAccountByUsername(String username) {
Account account = new Account();
account.setName(username);
account.setPassword(username);
account.setEmail(username);
return account;
}
public Account createNewAccount(String username){
//대충 새 유저를 생성하는 로직
return new Account();
}
}

애플리케이션을 구현하는 데 필요한 Account와 AccountService 클래스이다. 나는 이 두 클래스와 security 패키지의 기능을 엮어서 LoginHandler의 login 기능을 사용하고 싶다.


@AllArgsConstructor
public class AccountUserDetails implements UserDetails {
private Account account;
@Override
public String getUsername() {
return account.getName();
}
@Override
public String getPassword() {
return account.getPassword();
}
}
@AllArgsConstructor
public class AccountUserDetailsService implements UserDetailsService {
private AccountService accountService;
@Override
public UserDetails loadUser(String username) {
Account account = accountService.findAccountByUsername(username);
return new AccountUserDetails(account);
}
}

Account, AccountService와 연결하고 싶은 security 패키지의 두 인터페이스를 상속받아 어댑터의 역할을 하는 새 클래스를 정의했다.


public class LoginHandler {
private final UserDetailsService userDetailsService;
public LoginHandler(UserDetailsService userDetailsService){
this.userDetailsService = userDetailsService;
}
...
}

LoginHandler의 UserDetailsService위치에 AccountUserDetailsService를 주입하면 우리가 구현한 Account를 통해 login메서드를 사용할 수 있다.

링크로 가면 코드를 볼 수 있다.

출처:
https://www.inflearn.com/course/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B4