Spring

[Spring] 스프링 특징 - 변경 가능성

배씌 2024. 5. 22. 16:03

아래 코드는 (고정 할인 정책 / 변동 할인 정책) 중 결정 되지 않아, 변경 가능성이 있는 주문 Service 이다.

public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    // 변경 예정(FixDiscountPolicy() -> RateDiscountPolicy())
    private DiscountPolicy discountPolicy = new FixDiscountPolicy();

    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice){
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

위 코드의 할인 정책을 바꾸고 싶을 때, 단순히 new RateDiscountPolicy() 로 바꿔도 되긴 하지만 스프링의 컨셉에 어긋난다.

 

※ 문제점

  • 역할과 구현을 충실하게 분리했다 -> O
  • 다형성도 활용하고, 인터페이스와 구현 객체를 분리했다. -> O
  • OCP, DIP 같은 객체 지향 설계 원칙을 준수했다. -> X
    • DIP : 주문서비스 클라이언트('OrderServiceImpl') 는 ('DiscountPolicy') 인터페이스에 의존하면서 DIP를 지킨것 아니냐?
      • -> 추상(인터페이스) 뿐만 아니라, 구체(구현)클래스에도 의존하고 있다.
      • 추상(인터페이스) 의존 : 'DiscountPolicy'
      • 구체(구현)클래스 : 'FixDiscountPolicy' , 'RateDiscountPolicy'
    • 위 코드는 기능을 확장해서 변경하면, 클라이언트 코드에 영향을 준다. 따라서 OCP 위반!

해결 방법

 : 인터페이스에만 의존하도록 코드 수정

public class OrderServiceImpl implements OrderService{
    private final MemberRepository memberRepository = new MemoryMemberRepository();
    private DiscountPolicy discountPolicy; // 인터페이스에만 의존


    @Override
    public Order createOrder(Long memberId, String itemName, int itemPrice){
        Member member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

 

※ 그러나 위 형태로만 수정하면, Null Point Exception 에러 발생. 

-> 누군가가 클라이언트인 'OrderServiceImpl' 에 'DiscountPolicy' 의 구현 객체를 대신 생성하고 주입해줘야 함!

 

==> 빈(Bean)