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 위반!
- DIP : 주문서비스 클라이언트('OrderServiceImpl') 는 ('DiscountPolicy') 인터페이스에 의존하면서 DIP를 지킨것 아니냐?
해결 방법
: 인터페이스에만 의존하도록 코드 수정
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)