복습
저번 포스트에서는 회원 객체를 생성하고 , 로컬 Repository에 저장하기 위한 메소드와
이를 처리하기 위한 MemberService 를 정의하였다.이번 포스트에서는 저장과 할인 정책을 개발해본다.
요구사항
회원
회원을 가입하고 조회할 수 있다.
회원은 일반과 VIP 두 가지 등급이 있다.
회원 데이터는 자체 DB를 구축할 수 있고, 외부 시스템과 연동할 수 있다. (미확정)
주문과 할인 정책
회원은 상품을 주문할 수 있다. 회원 등급에 따라 할인 정책을 적용할 수 있다.
할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용해달라. (나중에 변경 될 수 있다.)
할인 정책은 변경 가능성이 높다. 회사의 기본 할인 정책을 아직 정하지 못했고, 오픈 직전까지 고민을 미루고 싶다.
최악의 경우 할인을 적용하지 않을 수 도 있다. (미확정)
1
2
3
4
5
6
7
8
9
|
package hello.core.discount;
import hello.core.member.Member;
public interface DiscountPolicy {
int discount(Member member , int price);
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package hello.core.discount;
import hello.core.member.Grade;
import hello.core.member.Member;
public class FixDiscountPolicy implements DiscountPolicy{
private int discountFixAmount = 1000;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP){
return discountFixAmount;
} else {
return 0;
}
}
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
package hello.core.discount;
import hello.core.member.Grade;
import hello.core.member.Member;
public class RateDiscountPolicy implements DiscountPolicy{
private int discountPercent = 10;
@Override
public int discount(Member member, int price) {
if(member.getGrade() == Grade.VIP){
return price * discountPercent / 100;
} else{
return 0;
}
}
}
|
cs |
-> 정률할인 정책과 고정 할인 정책 개발. Grade.VIP 일때만 할인이 들어간다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
package hello.core.order;
public class Order {
private Long memberId;
private String itemName;
private int itemPrice;
private int discountPrice;
public Order(Long memberId, String itemName, int itemPrice, int discountPrice) {
this.memberId = memberId;
this.itemName = itemName;
this.itemPrice = itemPrice;
this.discountPrice = discountPrice;
}
public Long getMemberId() {
return memberId;
}
public void setMemberId(Long memberId) {
this.memberId = memberId;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public int getItemPrice() {
return itemPrice;
}
public void setItemPrice(int itemPrice) {
this.itemPrice = itemPrice;
}
public int getDiscountPrice() {
return discountPrice;
}
public void setDiscountPrice(int discountPrice) {
this.discountPrice = discountPrice;
}
}
|
cs |
1
2
3
4
5
6
|
package hello.core.order;
public interface OrderService {
Order createOrder(Long memberId, String itemName , int itemPrice);
}
|
cs |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
package hello.core.order;
import hello.core.Repository.MemberRepository;
import hello.core.Repository.MemoryMemberRepository;
import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.Member;
public class OrderServiceImpl implements OrderService{
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
@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);
}
}
|
cs |
-> 주문에 관련된 로직 작성.
-> 할인 정책을 바꾸기 위해서는 Fix 또는 Rate 로 DiscountPolicy 를 바꾸어 주면 된다.
-> 각각의 Fix , Rate 라는 역할과 이를 구현한 객체들은 모두 분리돼있다.
-> 그렇지만 객체지향설계의 원칙을 지키지는 못했다.
-> OCP 위반 : 코드를 변경하지 않고 확장 가능해야 하는데 , 할인 정책이 바뀔때마다 직접 Fix --> Rate 로 변경이 일어난다.
-> DIP 위반 : OrderServiceImpl 은 추상 객체인 인터페이스 DiscountPolicy 뿐만 아니라 Fix, Rate 의 구체 클래스에도 의존한다.
- OrderServiceImpl 내의 코드 :
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
이는 추상과 구현 둘다 의존. 그렇지 않기 위해서는
private final DiscountPolicy discountPolicy ;
로 끝나야 한다. 만약 private final DiscountPolicy discountPolicy 처럼 바꾼다면 discountPolicy 는 어느 객체를 의존하고 있는지 알 수 없다. ( 해당 코드를 실행하면 Null Pointer Exception 발생)
※ 이를 해결하기 위해서 '의존성 주입 DI' (Dependency Injection) 이 필요하다.
- 다음 장에서는 의존성 주입에 대해 알아보고, 개발해보도록 하겠다.
* 해당 글은 'Infleran'의 김영한 강사님의 자료를 참조하였습니다.
'Spring > Spring Framework(Basic)' 카테고리의 다른 글
[Spring] Spring 을 이용하여 Service 구축하기 - 3 (0) | 2021.10.29 |
---|---|
[Spring] Spring 을 이용하여 Service 구축하기 - 2 (0) | 2021.10.28 |
[Spring] Spring 을 이용하여 Service 구축하기 - 1 (0) | 2021.10.28 |
[Spring] 순수 자바 코드를 이용해 Service 구축하기 - 3 (0) | 2021.10.28 |
[Spring] 순수 자바 코드를 이용해 Service 구축하기 - 1 (0) | 2021.10.26 |
댓글