본문 바로가기
Category/JAVA

[Design Pattern] Adapter Pattern의 실제 사용예시

by developer__Y 2024. 5. 23.

 

Adapter 패턴이란?

 

클라이언트가 호환되지않는 두개의 인터페이스를 기존의 인터페이스를 변경하지않고 Adapter를 통해 변환하여 사용할수있게 해주는 디자인 패턴.

Legacy코드에서 새로운 3rd Party 모듈을 추가하거나, 새로운 인터페이스로 교체할경우

기존의 Legacy코드를 변경하지않고 Adapter을 통해 사용할수있게 하므로 재사용성을 높일수 있다. 

 

출처: Java-Design-Patterns by Rohit Joshi

 

즉, 기존의 Current Code에서 타사의 API를 사용할경우, 중간 Adapter를 거치지않고 직접 Client와 연결 할경우

새로운 API로 교체하려면 Client가 기존의 API를 의존하기때문에 코드를 변경해주어야하고,

만약 연관된 Class가 100개라면 100개 모두 변경해줘야 할 것이다.

 

 

따라서, 기존의 Current Code와 API사이에 Adapter를 둬서, 어떠한 API에도 의존적이지 않고 새로운 인터페이스를 사용할수있도록 변환해주는 방법이 Adapter Pattern이다.

Adapter Pattern의 주요 구성요소로 Client , Target , Adapter , Adaptee가 있다.

 

Target : 새롭게 도입할 API

Adapter : 변환 어댑터 Class

Adaptee : 기존의 API

출처: Java-Design-Patterns by Rohit Joshi

 

 

실제 사용 예시 

 

실제로 Adapter Pattern이 어떠한 상황에서 사용되는지 예시와 예제코드를 작성해보자

 

 

소프트웨어 개발자 짱구는 전자상거래 웹사이트에서 일하고있다.

해당 사이트는 현재 카카오페이를 통해 사용자가 신용 카드를 사용하여 청구서를 지불할 수 있도록 하는 모듈이 통합되어 있다. 그런데, 갑자기 카카오페이가 아닌 네이버페이로 결제 모듈이 변경해야하는 작업을 진행해야한다.

여기서 발생하는 문제는 기존의 Legacy 코드는 KakaoPay 유형의 객체를 취하는 KakaoPay 결제 게이트웨이에 사이트가 연결되어 있고, 새로운 공급업체인 NaverPay는 NaverPay 유형의 객체만 프로세스를 허용하게 되어있다는 것이다.

그렇기에 기존의 Legacy에 연동되어있는 수백개의 Code 전체를 변경하는것은 굉장히 어렵고 복잡할 뿐더러

이미 실행 중인 프로젝트에 대한 위험을 증가시킬수있다.

 

 

이러한 상황에서 Adapter 패턴을 사용해 해당 문제상황을 유연하게 대처할수있다.

 

public interface KakaoPay {
	public String getCreditCardNo();
	public String getCustomerName();
	public String getCardExpMonth();
	public String getCardExpYear();
	public Short getCardCVVNo();
	public Double getAmount();
	
	public void setCreditCardNo(String creditCardNo);
	public void setCustomerName(String customerName);
	public void setCardExpMonth(String cardExpMonth);
	public void setCardExpYear(String cardExpYear);
	public void setCardCVVNo(Short cardCVVNo);
	public void setAmount(Double amount);
}

 

public class KakaoPayImpl implements KakaoPay{
	private String creditCardNo;
	private String customerName;
	private String cardExpMonth;
	private String cardExpYear;
	private Short cardCVVNo;
	private Double amount;
	
	@Override
	public String getCreditCardNo() {
		return creditCardNo;
	}

	@Override
	public String getCustomerName() {
		return customerName;
	}

	@Override
	public String getCardExpMonth() {
		return cardExpMonth;
	}

	@Override
	public String getCardExpYear() {
		return cardExpYear;
	}

	@Override
	public Short getCardCVVNo() {
		return cardCVVNo;
	}

	@Override
	public Double getAmount() {
		return amount;
	}

	@Override
	public void setCreditCardNo(String creditCardNo) {
		this.creditCardNo = creditCardNo;
	}

	@Override
	public void setCustomerName(String customerName) {
		this.customerName = customerName;
	}

	@Override
	public void setCardExpMonth(String cardExpMonth) {
		this.cardExpMonth = cardExpMonth;
	}

	@Override
	public void setCardExpYear(String cardExpYear) {
		this.cardExpYear = cardExpYear;
	}

	@Override
	public void setCardCVVNo(Short cardCVVNo) {
		this.cardCVVNo = cardCVVNo;
	}

	@Override
	public void setAmount(Double amount) {
		this.amount = amount;
	}
	
}

 

public class Client {
	public static void main(String args[]) {
		KakaoPay kakaoPay = new KakaoPayImpl();
		kakaoPay.setCreditCardNo("123456789");
		kakaoPay.setCustomerName("홍길동");
		kakaoPay.setCardExpYear("2029");
		kakaoPay.setCardExpMonth("07");
		kakaoPay.setCardCVVNo((short)2321);
		kakaoPay.setAmount(10000.00);
		
		System.out.println("------------- 기존 kakaoPay Module ----------");
		testKakao(kakaoPay);
	}
	public static void testKakao(KakaoPay kakaoPay) {
		System.out.println(kakaoPay.getCreditCardNo());
		System.out.println(kakaoPay.getCustomerName());
		System.out.println(kakaoPay.getCardExpYear());
		System.out.println(kakaoPay.getCardExpMonth());
		System.out.println(kakaoPay.getCardCVVNo());
		System.out.println(kakaoPay.getAmount());
	}

 

기존의 카카오페이 인터페이스와 구현클래스는 위와 같고,

Client에서 기존의 카카오페이 모듈을 위와 같이 사용하고 있는 상황에서

아래의 네이버페이 인터페이스를 신규로 사용해야한다.

 

public interface NaverPay {
	public String getCardNo();
	public String getOwnerName();
	public String getCardExpMMDD();
	public Integer getCVVNo();
	public Double getTotalAmount();
	
	public void setCardNo(String cardNo);
	public void setOwnerName(String ownerName);
	public void setCardExpMMDD(String cardExpMMDD);
	public void setCVVNo(Integer cVVNo);
	public void setTotalAmount(Double totalAmount);
}

 

 

// Kakao 모듈을  가지고 Naver 모듈사용할수있게 변환해주는 Adapter 클래스 생성
public class KakaoToNaverAdapter implements NaverPay {
	private String cardNo;
	private String ownerName;
	private String cardExpMMDD;
	private Integer cVVNo;
	private Double totalAmount;
//	기존 모듈을 Member로 선언
	private final KakaoPay kakaoPay;
	
//	기본 생성자 파라미터로 변환할 기존 모듈을 받아 setProperty.
	public KakaoToNaverAdapter(KakaoPay kakaoPay) {
		this.kakaoPay = kakaoPay;
		setProp();
	}
	
//	Kakao - Naver간 일치시킬 부분 Mapping
	private void setProp() {
		setCardNo(this.kakaoPay.getCreditCardNo());
		setOwnerName(this.kakaoPay.getCustomerName());
		setCardExpMMDD(this.kakaoPay.getCardExpMonth()+"/"+"00");
		setCVVNo(this.kakaoPay.getCardCVVNo().intValue());
		setTotalAmount(this.kakaoPay.getAmount());
		
	}
	@Override
	public String getCardNo() {
		// TODO Auto-generated method stub
		return cardNo;
	}

	@Override
	public String getOwnerName() {
		// TODO Auto-generated method stub
		return ownerName;
	}

	@Override
	public String getCardExpMMDD() {
		// TODO Auto-generated method stub
		return cardExpMMDD;
	}

	@Override
	public Integer getCVVNo() {
		// TODO Auto-generated method stub
		return cVVNo;
	}

	@Override
	public Double getTotalAmount() {
		// TODO Auto-generated method stub
		return totalAmount;
	}

	@Override
	public void setCardNo(String cardNo) {
		this.cardNo = cardNo;
		
	}

	@Override
	public void setOwnerName(String ownerName) {
		// TODO Auto-generated method stub
		this.ownerName = ownerName;
		
	}

	@Override
	public void setCardExpMMDD(String cardExpMMDD) {
		// TODO Auto-generated method stub
		this.cardExpMMDD = cardExpMMDD;
		
	}

	@Override
	public void setCVVNo(Integer cVVNo) {
		// TODO Auto-generated method stub
		this.cVVNo = cVVNo;
		
	}

	@Override
	public void setTotalAmount(Double totalAmount) {
		// TODO Auto-generated method stub
		this.totalAmount = totalAmount;
		
	}
	

}

 

 

Adapter를 통해 카카오페이를 가지고 네이버페이 모듈화 시켜 사용

 

public class Client {
	public static void main(String args[]) {
		KakaoPay kakaoPay = new KakaoPayImpl();
		kakaoPay.setCreditCardNo("123456789");
		kakaoPay.setCustomerName("홍길동");
		kakaoPay.setCardExpYear("2029");
		kakaoPay.setCardExpMonth("07");
		kakaoPay.setCardCVVNo((short)2321);
		kakaoPay.setAmount(10000.00);
		
		System.out.println("------------- 기존 kakaoPay Module ----------");
		testKakao(kakaoPay);
		
		NaverPay naverPayFromAdapter = new KakaoToNaverAdapter(kakaoPay);
		
		System.out.println("-----------adapter를 통한 변환 -----------");
//		KakaoPay 모듈의 클래스 변경없이 Adapter를 통해 기존의 Kakao 모듈을 가지고 NaverPay 모듈로 변환 
		testNaverFromKakao(naverPayFromAdapter);
		
	}
	public static void testNaverFromKakao(NaverPay naverPayFromAdapter) {
		System.out.println(naverPayFromAdapter.getCardNo());
		System.out.println(naverPayFromAdapter.getOwnerName());
		System.out.println(naverPayFromAdapter.getCardExpMMDD());
		System.out.println(naverPayFromAdapter.getCVVNo());
		System.out.println(naverPayFromAdapter.getTotalAmount());
	}
	public static void testKakao(KakaoPay kakaoPay) {
		System.out.println(kakaoPay.getCreditCardNo());
		System.out.println(kakaoPay.getCustomerName());
		System.out.println(kakaoPay.getCardExpYear());
		System.out.println(kakaoPay.getCardExpMonth());
		System.out.println(kakaoPay.getCardCVVNo());
		System.out.println(kakaoPay.getAmount());
	}
}

 

 

 

 

 

해당 예제는 JAVA-DESIGN-PATTERNS BY ROHIT JOSHI 를 참고하여 개인적으로 공부한 내용입니다.※