본문 바로가기
java

Design Patterns - Adapter

by 쭈꾸마뇽 2021. 11. 24.

기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴

클라이언트가 사용하는 인터페이스를 따르지 않는 기존 코드를 재사용할 수 있게 해준다

public class LoginHandler {

    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 IllegalArgumentException();
        }
    }
}

먼저 클라이언트쪽인 LoginHandler 클래스이다.  이 클래스는 UserDetailsService 인터페이스로부터 userName으로 UserDetails를 받아와 로그인 처리를 하는 로직이 있다.

public interface UserDetails {

    String getUsername();

    String getPassword();

}

 

public interface UserDetailsService {

    UserDetails loadUser(String username);

}
public class AccountService {

    public Account findAccountByUsername(String username) {
        Account account = new Account();
        account.setName(username);
        account.setPassword(username);
        account.setEmail(username);
        return account;
    }
}
public class Account {

    private String name;

    private String password;

    private String email;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

}

UserDetailsService는 AccountService와는 현재 연관관계가 없다.  하지만 UserDetailsService의 loadUser 메서드를 구현하기 위해서 AccountService가 필요하다.  그럴때 두 인터페이스간 연관관계를 이어주기 위해 어댑터를 구현해주면 소스코드의 수정 없이 AccountService의 메서드를 호출할 수 있다.

UserDetails 인터페이스도 Account 클래스와 연관관계가 없는데 위와 마찬가지로 어탭터를 구현해 연결해 줄 수 있다.

public class AccountUserDetails implements UserDetails {

    private Account account;

    public AccountUserDetails(Account account) {
        this.account = account;
    }

    @Override
    public String getUsername() {
        return account.getName();
    }

    @Override
    public String getPassword() {
        return account.getPassword();
    }
}

AccountUserDetails가 UserDetails를 구현한 일종의 어댑터이다.  Account를 인스턴스 변수로 갖고 사용해 UserDetails와 Account를 연결해 준다.

public class AccountUserDetailsService implements UserDetailsService {

    private AccountService accountService;

    public AccountUserDetailsService(AccountService accountService) {
        this.accountService = accountService;
    }

    @Override
    public UserDetails loadUser(String username) {
        return new AccountUserDetails(accountService.findAccountByUsername(username));
    }
}

 AccountUserDetailsService가 UserDetailsService를 구현한 일종의 어댑터이다.  AccountService를 인스턴스 변수로 갖고 사용해 UserDetailsService와 AccountService를 연결해 준다.

public class App {

    public static void main(String[] args) {
        AccountService accountService = new AccountService();
        UserDetailsService userDetailsService = new AccountUserDetailsService(accountService);
        LoginHandler loginHandler = new LoginHandler(userDetailsService);
        String login = loginHandler.login("keesun", "keesun");
        System.out.println(login);
    }
}
  • 장점
    • 기존 코드를 변경하지 않고 원하는 인터페이스 구현체를 만들어 재사용할 수 있다
    • 기존 코드가 하던 일과 특정 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다
  • 단점
    • 새 클래스가 생겨 복잡도가 증가할 수 있다.  경우에 따라서는 기존 코드가 해당 인터페이스를 구현하도록 수정하는 것이 좋은 선택이 될 수도 있다

 

 

코딩으로 학습하는 GoF의 디자인 패턴 - 인프런 | 강의

디자인 패턴을 알고 있다면 스프링 뿐 아니라 여러 다양한 기술 및 프로그래밍 언어도 보다 쉽게 학습할 수 있습니다. 또한, 보다 유연하고 재사용성이 뛰어난 객체 지향 소프트웨어를 개발할

www.inflearn.com

 

'java' 카테고리의 다른 글

Design Patterns - Composite  (0) 2021.11.29
Design Patterns - Bridge  (0) 2021.11.28
Design Patterns - Prototype  (0) 2021.11.22
Design Patterns - Builder  (0) 2021.11.21
Design Patterns - Abstract Factory  (0) 2021.11.20

댓글