1. 문제점
public class OrderServiceImpl implements OrderService {
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
}
할인정책 변경시, OrderServiceImpl 클래스를 고쳐야 함
이때
1) 인터페이스 뿐만 아니라 구현 클래스에도 의존: DIP 설계원칙 X
2) 기능 변경 시, 코드에 영향을 줌: OCP 설계 원칙 X
따라서 인터페이스에만 의존하도록 의존 관계를 변경하고
기능 변경시 코드에 영향을 주지 않도록 외부에서 구현 클래스를 주입해줘야 함!
2. AppConfig
어플리케이션의 구현 객체를 생성하고 연결을 책임지는 별도의 설정 클래스
...
import
...
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(new MemoryMemberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(new MemoryMemberRepository(),new FixDiscountPolicy());
}
}
구현클래스는 의존 관계에 대한 고민 없이 실행에만 집중
...
public class MemberServiceImpl implements MemberService {
// 인터페이스에만 의존, 객체는 외부로부터 주입
private final MemberRepository memberRepository;
public MemberServiceImpl(MemberRepository memberRepository) {
this.memberRepository = memberRepository;
}
...
// service 기능
...
}
appConfig 객체는 memberServiceImpl 이 생성될 때 memoryMemberRepository 객체 생성해 전달한다 (생성자)
memberServiceImpl 의 의존 관계는 외부에 의해서 주입되며 이를 DI, 의존 관계 주입 이라 함
AppConfig 처럼 객체를 생성하고 관리하면서 의존관계를 연결해 주는 것을
Ioc 컨테이너 또는 DI 컨테이너 라 함
중복 부분이 제거되도록 리팩토링하면
...
import
...
public class AppConfig {
public MemberService memberService() {
return new MemberServiceImpl(memberRepository());
}
public OrderService orderService() {
return new OrderServiceImpl(memberRepository(),discountPolicy());
}
public MemberRepository memberRepository() {
return new MemoryMemberRepository();
}
public DiscountPolicy discountPolicy() {
return new FixDiscountPolicy();
// 할인 정책을 바꾸고 싶을 때
// return new RateDiscountPolicy();
}
}
3. 좋은 객체 지향 설계의 5가지 원칙
1. SRP, 단일 책임 원칙: 하나의 클래스는 하나의 책임만 가진다
구현 클래스 생성과 연결은 AppConfig 가 담당
구현 클래스는 실행하는 책임만을 담당
2. DIP, 의존 관계 역전 원칙: 구체화가 아닌 추상화에 의존하라
구현 클래스 코드는 인터페이스에 의존하도록 설계
3. OCP, 개방 폐쇄 원칙: 소프트웨어는 확장에는 열려있으나 변경에는 닫혀있게
소프트웨어 요소를 확장해도 구현 클래스는 변경되지 않도록
4. ISP, 인터페이스 분리 원칙: 인터페이스는 무겁지 않게
하나의 무거운 인터페이스보다 여러개의 가벼운 인터페이스가 낫다.
5. LSP, 리스코프 치환 원칙: 하위클래스는 상위클래스를 대체 가능하게
하위 클래스가 상위클래스를 오버라이드 하거나 확장 가능
4. 기타 코멘트
- 스프링은 DI 와 컨테이너를 통해 OCP,DIP 를 가능하게 지원, 코드 변경없이 기능을 확장하고 교체
- 스프링은 다형성을 극대화함 -> 무대 위 배우 바꾸듯 편리하게~
- 이러한 변경에 유연한 장점 때문에 대규모 프로젝트에 매우 적합!
- 인터페이스 >> 구현, 인터페이스를 안정적으로 설계하는 것이 매우 중요
- final 키워드: 수정 불가, 안정성과 불변성을 확보하는 키워드
'백앤드 개발 > Java & Spring' 카테고리의 다른 글
[Java] 참조형 변수 (0) | 2023.11.07 |
---|---|
[Spring boot] 회원, 주문 프로젝트 - 스프링으로 전환 (0) | 2023.11.07 |
[Spring boot] 회원, 주문 프로젝트 - 설계 및 구현 (0) | 2023.11.06 |
[Spring boot] JPA와 스프링 데이터 JPA (0) | 2023.10.31 |
[Spring boot] 프로젝트 환경 설정과 Spring 어플리케이션 구조 (0) | 2023.10.25 |