예시)
@mapper
public interface ExampleMapper {
List<ExampleDto> findExampleList();
ExampleDto findExampleById(String id);
}
구현체
<select id="findExampleList">
SELECT *
FROM EXAMPLE
</select>
<select id="findExampleById">
SELECT *
FROM EXAMPLE
WHERE ID = #{id}
</select>
private final DiscountPolicy = new FixDiscountPolicy();
클라이언트 - > 회원 서비스 -> (메모리)회원 저장소
private final DiscountPolicy = new FixDiscountPolicy();
하지만 이 방식은 interface를 통해서 역할과 기능을 분리하는 줄 알았는데
FixDiscountPolicy 대신 DiscountPolicy 로 정책을 변경하게 된다면 *orderServiceImpl에서 코드를 수정해 줘야하는 상황이 발생한다.
//private final DiscountPolicy = new FixDiscountPolicy();
private final DisocuntPolicy = new RateDiscountPolicy();
해결 방안
- 구현체에 의존하지 않도록 동적할당 하는 부분을 삭제해주면 되지 않을까?
- 하지만 기존 코드에서 구현체를 삭제하면 Null Point Exception 발생!!
- 누군가가 클라이언트인 OrderServiceImpl에 discountPolicy의 구현객체를 대신 생성하고 주입 해주면 되지 않을까??
관심사를 분리해야 한다!!
"기획자의 등장" '누가' 어떤 역할에 배우를 넣어줄지 정하는 일은 배우가 하는 것이 아닌 어떤 '무엇'인가가 하는 일
@Configuration
public class AppConfig {
@Bean
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
@Bean
public static MemoryMemberRepository memberRepository() {
return new MemoryMemberRepository();
}
@Bean
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(), discountPolicy());
}
@Bean
public static FixDiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
}
}
public class OrderApp {
public static void main(String[] args) {
AppConfig appConfig = new AppConfig();
MemberService memberService = appConfig.memberService();
OrderService orderService = appConfig.orderService();
Long memberId = 1L;
Member member = new Member(memberId, "memberA", Grade.VIP);
memberService.join(member);
Order order = orderService.createOrder(memberId, "itemA", 10000);
System.out.println("order = " + order);
}
}
- AppConifg 객체는 각 Interface 어떤 구현 객체를 넣어줄지 동적으로 할당해 주었다.
- OrderApp 객체는 AppConfig 를 호출해서 MemberService Interface와 OrderService Interface가 어떤 구현 객체를 사용할 지는 생성자를 호출하는 시점, Runtime(실행시점) 에 알 수 있게 한다. 즉, 오직 기능에 초점을 두었다.
- DIP 완성: MemoryServiceImpl은 memberRepository인 추상화에만 의존하면 된다. 다시 말해 AppConfig를 통해서 구현 객체는 그 기능 자체에만 집중을 할 수 있게 되었다.
구현객체를 생성하고 연결하는거는 AppConfig가 담당
클라이언트 객체는 실행만 담당
AppConfig가 의존 관계를
FixDiscountPolicy -> RateDiscountPolicy
로 변경해서 클라이언트 코드에 주입하므로 클라이언트 코드를 변경하지 않아도 된다.