기존 코드는
이렇게 추상화와 구현체에 모두 의존하고 있지만
이를 생성자를 통해서 분리해주면 아래와 같은 코드가 되면서 MemberServiceImpl에서는 MemoryMemberRepository()인 구현체에 대해서는 의존하지 않기 때문에, DIP를 위반하지 않게된다.
대신 AppConfig에서 MemberService인터페이스는 그의 구현체인 MemberServiceImpl을 부르고, 구현체를 부를때 인수를 통해 MemoryMemberRepository를 생성해서 넣어주게 된다. (생성자 주입)
- 설계 변경으로 MemberServiceImpl 은 MemoryMemberRepository 를 의존하지 않는다!
- 단지 MemberRepository 인터페이스만 의존한다.
- MemberServiceImpl 입장에서 생성자를 통해 어떤 구현 객체가 들어올지(주입될지)는 알 수 없다.
- MemberServiceImpl 의 생성자를 통해서 어떤 구현 객체를 주입할지는 오직 외부( AppConfig )에서 결정된다.
- MemberServiceImpl 은 이제부터 의존관계에 대한 고민은 외부에 맡기고 실행에만 집중하면 된다.
- 객체의 생성과 연결은 AppConfig 가 담당한다.
- 관심사의 분리: 객체를 생성하고 연결하는 역할과 실행하는 역할이 명확히 분리되었다.
- DIP 완성: MemberServiceImpl 은 MemberRepository 인 추상에만 의존하면 된다. 이제 구체 클래스를 몰라도 된다.
OrderService도 위와 같이 수정할 수 있다.
이렇게 되면 아주 깔끔하게 DIP를 지킬 수 있다.
- AppConfig는 애플리케이션의 실제 동작에 필요한 구현 객체를 생성한다.
- MemberServiceImpl
- MemoryMemberRepository
- OrderServiceImpl
- FixDiscountPolicy
- AppConfig는 생성한 객체 인스턴스의 참조(레퍼런스)를 생성자를 통해서 주입(연결)해준다.
- MemberServiceImpl MemoryMemberRepository
- OrderServiceImpl MemoryMemberRepository , FixDiscountPolicy
<정리>
- AppConfig를 통해서 관심사를 확실하게 분리했다.
- 배역, 배우를 생각해보자.
- AppConfig는 공연 기획자다.
- AppConfig는 구체 클래스를 선택한다. 배역에 맞는 담당 배우를 선택한다. 애플리케이션이 어떻게 동작해
- 야 할지 전체 구성을 책임진다.
- 이제 각 배우들은 담당 기능을 실행하는 책임만 지면 된다.
- OrderServiceImpl 은 기능을 실행하는 책임만 지면 된다.
'Back End > Spring' 카테고리의 다른 글
Spring - 지금까지의 전체 흐름 정리 (0) | 2023.07.07 |
---|---|
Spring - AppConfig (0) | 2023.07.07 |
spring - 회원 도메인 설계 (0) | 2023.07.06 |
Spring - springboot 초기 설정 (0) | 2023.07.06 |
좋은 객체 지향 설계의 5가지 원칙 (SOLID) (0) | 2023.07.05 |