티스토리 뷰

디자인 패턴

06. 어댑터 패턴

jin-park 2022. 2. 10. 17:06

1.  의미

  • 기존 코드를 클라이언트가 사용하는 인터페이스의 구현체로 바꿔주는 패턴
  • 인터페이스를 따르지 않는 기존 코드를 재사용 할수 있음.

다이어그램

2.  예제

2.1.  security package

  • 예제로security 패키지 안에 로그인 관련 기능을 라이브러리 형식으로 제공해주고 있음.
/**
 * 회원 정보
 */
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 = this.userDetailsService.loadUser(username);
        if (userDetails.getPassword().equals(password)) {
            return userDetails.getUserName();
        } else {
            throw new IllegalArgumentException();
        }
    }
}

2.2.  client

  • 클라이언트에서 사용하는 계정 정보 및 처리하는 서비스는 라이브러리와 다른형식으로 사용되고 있음.
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; }
}
public class AccountService {
 
    public Account findAccountByUsername(String username) {
        Account account = new Account();
        account.setEmail(username);
        account.setName(username);
        account.setPassword(username);
 
        return account;
    }
 
    public void createNewAccount(Account account) {
 
    }
 
    public void updateNewAccount(Account account) {
 
    }
}

2.3.  Adapter 패턴 적용

2.3.1.  기존 코드를 수정 불가한 경우

  • 형식이 다른 두 인터페이스를 이어주는 어댑터 클래스를 생성한다.
    • AccountService ↔ UserDetailsService
    • Account ↔ UserDetails
public class AccountUserDetailsService implements UserDetailsService {
 
    private final AccountService accountService;
 
    public AccountUserDetailsService(AccountService accountService) {
        this.accountService = accountService;
    }
 
    @Override
    public UserDetails loadUser(String username) {
        Account account = this.accountService.findAccountByUsername(username);
        return new AccountUserDetails(account);
    }
}
public class Client {
 
    public static void main(String[] args) {
        AccountService accountService = new AccountService();
        AccountUserDetailsService accountUserDetailsService = new AccountUserDetailsService(accountService);
        LoginHandler loginHandler = new LoginHandler(accountUserDetailsService);
        String login = loginHandler.login("jin", "jin");
        System.out.println(login);
    }
 
}

2.3.2.  기존 코드를 수정 가능한 경우

  • 사용하고자 하는 인터페이스를 직접 구현한다.
  • 기존 코드를 수정해야하는 단점이 있으나 새로운 클래스를 생성하지 않아도 되어 복잡도가 낮아지는 장점이 존재함.
class Account implements UserDetails {
    private String name;
    private String password;
    private String email;
 
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }
 
    // UserDetails 구현으로 추가됨
    @Override public String getUserName() { return this.name; }
    @Override 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; }
}
public class AccountService implements UserDetailsService {
    public Account findAccountByUsername(String username) {
        Account account = new Account();
        account.setEmail(username);
        account.setName(username);
        account.setPassword(username);
 
        return account;
    }
     
    ....
    ....
 
    @Override
    public UserDetails loadUser(String username) {
        return this.findAccountByUsername(username);
    }
}

3.  장점 및 단점

3.1.  장점

  • 기존코드를 변경하지 않고 인터페이스 구현체를 만들어 재사용이 가능하다.
  • 기존 코드가 하던 일과 인터페이스 구현체로 변환하는 작업을 각기 다른 클래스로 분리하여 관리할 수 있다.

3.2.  단점

  • 어댑터 클래스가 생기므로 복잡도가 증가한다.
    • 경우에 따라서 기존코드가 인터페이스를 구현하도록 수정하는것이 좋은 선택일 수 있다.

위글은 인프런의 코딩으로 학습하는 GoF의 디자인 패턴강의를 정리하였습니다.

백기선님의 수락으로 정리하였으며 더 자세한 내용은 강의를 수강하시기 바랍니다.

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

 

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

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

www.inflearn.com

 

'디자인 패턴' 카테고리의 다른 글

08. 컴포짓 패턴  (0) 2022.02.10
07. 브릿지 패턴  (0) 2022.02.10
05. 프로토타입 패턴  (0) 2022.02.10
04. 빌더패턴  (0) 2022.02.10
03. 추상 팩토리 패턴  (0) 2022.02.10
댓글