Spring 핵심 원리 - 주문과 할인 도메인 구현

김태훈·2023년 1월 5일
0

Spring 핵심 원리

목록 보기
4/15
  • 주문과 할인 정책
    회원은 상품을 주문할 수 있다.
    회원 등급에 따라 할인 정책을 적용할 수 있다.
    할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용한다 (나중에 변경 될 수
    있다.)
    할인 정책은 변경 가능성이 높다. (미확정)

다음의 요구사항을 보고 개발을 진행해보자.

1. 알고리즘

1. 클라이언트 (main, MVC 컨트롤러 등등..) 에서 주문 정보를 주문 서비스 역할에 넘김. (주문 생성)

이 때, 회원 ID, 상품명, 상품 가격이 포함됨

2. 할인을 위해서 회원 등급을 살펴보아야 함. 회원 저장소 (Repository) 확인

3. 회원 등급 확인후 할인 정책 역할을 반영

4. 클라이언트로 다시 주문 결과 반환

(주문 서비스를 DB에 저장하는 과정은 생략)

이 때, 역할과 구현을 분리해놓으면, 저장소나, 할인 정책을 쉽게 조립할 수 있기 때문에 더 좋을 수 밖에 없다.

출처 : 김영한님 스프링 강의

2. 코드 작성

1. discount 폴더 생성

2. DiscountPolicy 인터페이스 생성

package Goat.core.discount;

import Goat.core.member.Member;

public interface DiscountPolicy {
    //return 은 할인 대상 금액
    int discount(Member member, int price);

}

3. 정액 할인 정책 (Fix Discount Policy)

package Goat.core.discount;

import Goat.core.member.Grade;
import Goat.core.member.Member;

public class FixDiscountPolicy implements DiscountPolicy{

    private int discountFixAmount = 1000;  //1000원 할인
    @Override
    public int discount(Member member, int price) {
        if (member.getGrade() == Grade.VIP ){
            return discountFixAmount;
        }
        else{
            return 0;
        }
    }
}

4. 주문 정보 구현하기

package Goat.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 int calculatePrice(){
        return itemPrice - 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;
    }
}

이 때, 최종 가격을 얻어내기 위해, calculatePrice함수가 추가로 작성되었다.

Integer와 int 무엇이 다른가?
앞에보면 itemPrice와 discountPrice에 Integer가 아닌 int가 쓰였다.
int : 변수형 타입 -> 산술 연산 가능, null로 초기화 불가
Integer : wrapper class 로 '객체' -> 연산을 위해 형변환 필수, null 값 처리 가능

5. 주문 서비스 Interface 생성

package Goat.core.Order;

import org.springframework.core.annotation.Order;

public interface OrderService {

    Order createOrder(Long memberId, String itemName, int itemPrice);
}

클라이언트에서 주문을 넣을 때 세가지 정보롤 함으로, 이 정보를 통해 주문 서비스 생성

6. 주문 서비스 구현하기

package Goat.core.order;

import Goat.core.discount.DiscountPolicy;
import Goat.core.discount.FixDiscountPolicy;
import Goat.core.member.Member;
import Goat.core.member.MemberRepository;
import Goat.core.member.MemoryMemberRepository;

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 resultMember = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(resultMember,itemPrice);

        return new Order(memberId, itemName, itemPrice, discountPrice);
    }
}

주문 서비스 구현에는
1. 멤버들의 등급이 필요 -> repository를 받아와야 한다.
2. 할인 정책이 필요 -> discountPolicy 를 받아온다.

그리고, 여기에는 SOLID중 S(SRP-단일체계원칙)이 잘 지켜졌다.
Order에서 처리하고자 하는 것은 주문과 관련된 것들만 하는 것이지, 할인에 대한 것은 전적으로 DiscountPolicy에게 넘긴다.

profile
기록하고, 공유합시다

0개의 댓글