
역할과 구현을 분리하여 OOP 즉 객체 지향을 지키면서 SRP, OCP, DIP 등을 따르면서 구현을 한다면 아래와 같은 형태일 것 이다.

하지만 순수 Java 코드로 구현을 하다보니
public class OrderServiceImpl implements OrderService {
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
// 고정 할인 정책
}
위와 같이 구현이 되었다.
위와 같은 경우에서는 만약 고정 할인 정책을 다른 할인 정책으로 바꿔주게 된다면 구현쪽 클래스의 코드 또한 변경을 해줘야 하는 문제점이 생긴다.
왜 그럴까?
위의 의존 관계를 분석해보면 인터페이스만이 아닌 아래와 같이 구현 클래스에도 의존을 하고 있다.

이 문제를 해결하기 위해서는 OderServiceImpl 에 DiscountPolicy의 구현 객체를 대신 생성하고 주입 해주어야 한다.
애플리케이션의 전체 동장 방식을 구성(config) 하기 위해, 구현 객체를 생성하고, 연결하는 역할을 가지는 별도의 설정 클래스를 만들자.
public class AppConfig {
public OrderService orderService() {
return new OrderServiceImpl(
memberRepository(),
discountPolicy());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
return new RateDiscountPolicy();
}
}
그리고 OrderSerivceimpl 에는 생성자를 주입한다.
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository;
private final DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicydiscountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
기존 프로그램은 클라이언트 구현 객체가 스스로 서버 구현 객체를 생성 ,연결 ,실행 했다.
반면 AppConfig 의 등장 이후에 프로그램의 제어 흐름을 모두 AppConfig 가 가져간다.
OrderServiceImple 또한 AppConfig 가 생성하고 할당한다.
이렇듯 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것을 IoC이라 한다.

<출처 : 스프링 핵심 원리 - 기본편 by 김영한>
좋은 글 감사합니다.