더보기
인프런: 스프링 핵심 원리 - 기본편 강의를 듣고 작성된 글 입니다.
OCP, DIP 위반하는 경우
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
//private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
}
해당 코드는 지금 DIP, OCP 모두 위반하고 있다.
- 추상 인터페이스(MemberRepository, DiscountPolicy)와 구체 클래스(MemoryMemberRepository, FixDiscountPocily, RateDiscountPolicy) 함께 의존 -> DIP 위반
- FixDisplayPolicy() -> RateDiscountPolicy()로 변경할 때 클라이언트(OrderServiceImpl)도 변경-> OCP 위반
인터페이스만 의존할 수 있도록 코드를 변경해보았다.
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
private DiscountPolicy discountPolicy;
}
실행 결과 NullPointerException이 발생한다.
따라서, 대신 생성하고 주입해줘야한다.
어떻게 구현할 수 있을까?
관심사의 분리: 객체를 생성하고 연결하는 역할 / 실행하는 역할 분리
위의 문제를 해결하기 위해서는 AppConfig 라는 클래스를 따로 만들어주어야한다.
Appconfig 는 구현 객체를 생성하고 연결한다.
먼저, OrderServiceImpl에서 생성자를 생성하고 추상화 인터페이스만 의존할 수 있도록 변경한다.
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
}
Appconfig에서 MemoryMemberRepository와 FixDiscountPolicy 두 객체 인스터스를 생성하고 생성자를 통해 구체 클래스를 주입한다.
public class AppConfig {
public OrderService orderService() {
return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
}
}
- OrderServiceImple에서는 생성자로 주입받을 수 있고 해당 클래스에서는 추상화 인터페이스만 의존할 수 있게 된다.
- FixDisplayPolicy() -> RateDiscountPolicy()로 변경할 때에도 AppConfig에서 변경되기 때문에 클라이언트 코드는 변경하지 않게 된다.
구현 객체를 생성하고 연결하는 책임은 AppConfig, 클라이언트 객체는 실행하는 책임만 담당하게 되면서 SRP 단일 책임 원칙도 지키게 된다.
-> SRP, DIP, OCP 완성
OrderServiceImple 입장에서는 의존관계를 마치 외부에서 주입해주는 것 같다고 해서 DI(Dependency Injection) : 의존관계 주입이라고 한다.
'Spring' 카테고리의 다른 글
Spring이란 무엇인가 (0) | 2024.08.15 |
---|