객체지향 원리 DIP, OCP
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
// FixDiscountPolicy -> RateDiscountPolicy로 바꾸기 위해 코드 변경
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
@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);
}
}


문제점 : 인터페이스에 의존해야하는데, 인터페이스와 구체클래스 모두 의존 -> DIP위반

문제점 : 변경하지 않고 확장 할 수 있어야 하는데, 지금 코드는 기능을 확장해서 변경하면, 클라이언트 코드에 영향을 준다 -> OCP위반
해결방안 : 누군가가 클라이언트인 ServiceImpl에 DiscountPolicy의 구현 객체를 대신 생성하고 주입해야 한다.
public class OrderServiceImpl implements OrderService {
private MemberRepository memberRepository;
private DiscountPolicy discountPolicy;
public OrderServiceImpl(MemberRepository memberRepository, DiscountPolicy discountPolicy) {
this.memberRepository = memberRepository;
this.discountPolicy = discountPolicy;
}
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(new MemoryMemberRepository(), new FixDiscountPolicy());
}
}
-> 외부에서 생성자를 통해 주입

AppConfig리펙토링
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@NotNull
private MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
새로운 구조와 할인 정책 적용
AppConfig의 등장으로 사용 영역과 객체를 생성하고 구성하는 영역으로 나뉘었다.

public DiscountPolicy discountPolicy() {
// return new FixDiscountPolicy();
return new RateDiscountPolicy();
}
}
ServiceImpl 바꿀 필요 x -> AppConfig만 수정하면 된다.
좋은 객체 지향 설계의 5가지 원칙의 적용

IoC, DI, 그리고 컨테이너
정적인 클래스 의존관계
IoC 컨테이너, DI컨테이너
- AppConfig처럼 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것을 IoC컨테이너 또는 DI컨테이너라고 한다.
ctrl + b : 이동
crtl + alt + v : 클래스 객체 생성