Computer Science

Adapter Pattern | 어댑터패턴

연_우리 2022. 8. 14. 23:37
반응형

 

 

 

 

어떤 상황에서 쓰일까?

항상 나오는 예시.. 한국 전기제품 220V와 미국 전기제품 110V 사이에 꽂아서 전압을 맞추어주는 것을 어댑터라고한다!

소프트웨어에서도 동일하게, 서로 다른 인터페이스를 맞추어서 사용할 수 있게 해준다.

 

 

 

어댑터 패턴이란?

규격에 맞지 않는 객체를

클라이언트가 사용하는 인터페이스의 구현체로 바꾸어주는 패턴이다.

 

 

 

장점

- 기존 코드(Account)를 변경하지 않고 원하는 인터페이스 구현체(AccountUserDetails)를 만들어 재사용할 수 있다.

 

단점

- 새 클래스(AccountUserDetails)가 생겨 복잡도가 증가할 수 있다.

 

 

 

구현방법

기존코드

 

Security에서 제공하는 LoginHandler. Security 패키지에 있는 코드는 건드릴 수 없다고 가정한다!!!

public interface UserDetails {
    String getUsername();
    String getPassword();
}


public interface UserDetailsService {
	UserDetails loadUser(String username);
}
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();
        }
    }
    
}

 

 

우리가 만든 Application에서 사용하는 계정정보

@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);
        acoount.setEmail(username);
        return account;
    }
}

 

 

UserDetails를 Account와 호환시키고,

UserDetailsService를 AccountService와 호환시키려면 어떻게해야할까?

 

 

 

 

변경코드

//시큐리티 패키지에 있는 UserDetails를 구현한다
public class AccountUserDetails implments UserDetails {

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

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

}
//시큐리티 패키지의 인터페이스를 구현한다
public class AccountUserDetailsService implements UserDetailsService {

    AccountService accountService;
    public AccountUserDetailsService(AccountService accountService){
    	this.accountService = accountService;
    }   
    
    @Override
    public UserDetails loadUser(String username){
    	Account account = accountService.findByAccountByUsername(username);
       	//우리 서비스에서 Account를 찾는다 
       
        return new AccountUserDetails(account);
        //account를 넘겨주면 AccountUserDetails에서 Account를 UserDetails에 맞게 변환한다 (어댑터!)
    }
   	
}
public class App {

    public static void main(String[] args) {
    
        AccountService accountService = new AccountService();
        UserDetailsService userDetailsService = new AccountUserDetailsService(accountService);
        //Account를 UserDetails로 변환해주는 AccountUserDetailsService를 생성한다
        
        LoginHandler loginHandler = new LoginHandler(userDetailsService);
        //로그인 핸들러에 주입하여 Account가 UserDetails로 변환되도록 한다
        
        String login = loginHandler.login("keesun", "keesun");
        System.out.println(login);
        
    }
}

 

LoginHandler <- UserDetailsService <- UserDetails

 

UserDetailsService <- AccountUserDetailsService <- AccountService

 

UserDtails <- AccountUserDetails <- Account 

 

두개의 어댑터를 생성하여 Security패키지의 코드를 건들 수 없는 상황에서

우리의 애플리케이션과 호환되도록 처리할 수 있게되었다!

 

 

 

 

 

반응형
  • 네이버 블러그 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 구글 플러스 공유하기
  • 카카오톡 공유하기