𝑺𝒕𝒖𝒅𝒚/디자인 패턴

[JAVA/Spring Boot] getter interface를 활용해 OCP를 준수한 SapMapper 구현하기

⌨️ 코드 구현

@Component
public class SapMapper {

    public SapSendDto toDto(Sales sales){
        return new SapSendDto(
                sales.getAmount(),
                sales.getPrice()
        );
    }

    public SapSendDto toDto(Purchase purchase) {
        return new SapSendDto(
                purchase.getAmount(),
                purchase.getPrice()
        );
    }
}

기존 SapMapper는 Sales와 Purchase 각각에 대해 toDto 메서드를 오버로딩한 형태로 구성되어 있다. 또한 두 메서드 모두 getAmount()와 getPrice()로 값을 받아와 SapSendDto를 만드는 동일한 역할을 수행한다.

만약 새로운 요구사항으로 Mortgage를 만들어야 한다면 toDto(Mortgage mortgage) 메서드를 추가해야 하는 상황이 발생한다.

⇒ OCP(개방 폐쇄 원칙)를 위반하고 있음

제약사항

  • SapMapper와 domain만 수정

접근방식

알고리즘 전략을 캡슐화하고 런타임에 선택할 수 있게 하는 **전략 패턴(Strategy Pattern)**을 활용했다.

전략 패턴에 대한 간략한 설명과 구현 예시는 https://jin-nie.tistory.com/4 에서 확인할 수 있습니다!

각 도메인이 getter interface를 구현하고, SapMapper는 해당 인터페이스에만 의존하는 구조로, 새로운 도메인이 추가되어도 SapMapper는 수정하지 않아도 되므로 OCP를 준수할 수 있다.

인터페이스

import java.math.BigDecimal;

public interface SapDataProvider {

    BigDecimal getAmount();
    BigDecimal getPrice();
}

Sales와 Purchase가 공통으로 사용하는 getAmount()와 getPrice() 메서드를 인터페이스로 추출

각각의 도메인 클래스가 인터페이스를 구현하면 SapMapper는 구체적인 타입 없이 동일한 방식으로 데이터를 사용 가능

SapMapper

@Component
public class SapMapper {

    public SapSendDto toDto(SapDataProvider sapDataProvider){
        return new SapSendDto(
                sapDataProvider.getAmount(),
                sapDataProvider.getPrice()
        );
    }
}

SapMapper의 메서드 파라미터 타입을 SapDataProvider 인터페이스로 변경하여 두 개의 메서드를 단일 메서드로 통합

  • Mortgage 같은 새로운 요구사항이 발생하더라도 SapMapper를 수정하지 않고 바로 사용할 수 있게 됨

추가사항

public interface SapDataProvider {

    default BigDecimal getAmount() { return null; }
    default BigDecimal getPrice() { return null; }
}

인터페이스를 위와 같이 구현한다면 새로운 요구사항에 AmountPrice가 존재하지 않을 때에도 불필요한 구현 없이 사용할 수 있다.

## COMMENTS
> SEARCH: