SPRING 핵심 원리 [ 기본편 ]

[스프링 핵심 원리] 섹션 2.7 예제만들기 (주문과 할인 도메인 개발)

wlalsu_u 2023. 1. 24. 15:35

2.7.1  할인 도메인 개발

 

 

 

앞선 섹션 2.6의 회원 도메인 설계를 바탕으로 회원 도메인을 개발해보자.

 

 

 

 

먼저, 할인 정책을 설정하기 위해 main  >  java  >  hello.core 에 discount 패키지를 생성하고,

 

DiscountPolicy 인터페이스를 다음과 같이 작성한다.

 

 

 

 

package hello.core.discount;

import hello.core.member.Member;

public interface DiscountPolicy {

    /**
     * @return 할인 대상 금액
     */
    int discount(Member member, int price);
}

 

 

 

int discount(Member member, int price)

 

 

: 파라미터로 멤버 객체와 가격을 넘기는 discount 메소드를 작성하도록 한다.

 

: return 값으로 할인된 금액을 넘겨주도록 한다.

 

 

 

 


 

 

 

 

다음으로, DicountPolicy 인터페이스를 구현하는 FixDiscountPolicy 클래스를 작성해보자.

 

동일하게 discount 패키지 아래에 작성한다.

 

 

 

 

package hello.core.discount;

import hello.core.member.Grade;
import hello.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;
        }
    }
}

 

 

 

 

public class FixDiscountPolicy implements DiscountPolicy

 

 

: DicountPolicy 인터페이스를 구현하도록 작성한다.

 

 

 

if (member.getGrade() == Grade.VIP)

 

 

: dicount 메소드 오버라이딩에서, 회원 등급이 VIP 인 경우, 1000원을 할인 금액으로 반환한다.

 

 

 

else return 0

 

 

: 회원 등급이 BASIC 인 경우, 할인 금액을 0으로 반환한다.

 

 

 

 


 

 

 

2.7.2  주문 도메인 개발

 

 

 

먼저 주문 데이터를 저장하기 위해 main  >  java  >  hello.core 에 order 패키지를 생성하고,

 

Order 클래스를 다음과 같이 작성한다.

 

 

 

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 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;
    }

    @Override
    public String toString() {
        return "Order{" +
                "memberId=" + memberId +
                ", itemName='" + itemName + '\'' +
                ", itemPrice=" + itemPrice +
                ", discountPrice=" + discountPrice +
                '}';
    }
}

 

 

 

Long memberId, String itemName, int itemPrice, int discountPrice

 

 

: 회원 아이디, 회원 이름, 상품 이름, 상품 가격 을 저장하는 주문 클래스를 생성한다.

 

 

Order 생성자

 

 

Getter and Setter

 

 

: 데이터를 가져오고 사용할 수 있도록 get 과 set 메소드를 생성한다.

 

( window 의 경우 Alt + insert 를 이용하여 자동 생성 가능)

 

 

 

 

public int calculatePrice()

 

 

: 원가에서 할인 금액을 빼는 비즈니스 로직을 추가한다.

 

 

 

 

 


 

 

 

다음으로, OrderService 인터페이스 order 패키지에 생성하고,

 

다음과 같이 작성한다.

 

 

 

package hello.core.order;

public interface OrderService {
    Order createOrder(Long memberId, String itemName, int itemPrice);
}

 

 

: 회원 아이디, 상품 명, 상품 가격을 파라미터로 넘기고, 주문 결과를 반환하도록 한다.

 

 

 

 


 

 

 

 

앞선 OrderService 인터페이스를 구현하는 OrderServiceImpl 클래스를 작성해보자.

 

 

 

package hello.core.order;

import hello.core.discount.DiscountPolicy;
import hello.core.discount.FixDiscountPolicy;
import hello.core.member.Member;
import hello.core.member.MemberRepository;
import hello.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 member = memberRepository.findById(memberId);
        int discountPrice = discountPolicy.discount(member, itemPrice);

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

 

 

 

private final MemberRepository memberRepository = new MemoryMemberRepository();

 

 

: 주문 생성 요청이 왔을 때, 회원 정보를 조회하기 위해 저장소가 필요하다.

 

 

 

private final DiscountPolicy discountPolicy = new FixDiscountPolicy();

 

 

: 회원 정보를 조회한 후 할인 정책을 적용하기 위해 필요하다.

 

( 고정 금액 할인 정책을 구현체로 생성하였다.)

 

 

 

int discountPrice = discountPolicy.discount(member, itemPrice)

 

 

: createOrder 메소드를 오버라이딩 하여, 회원 객체를 하나 생성하고,

 

회원 등급에 따른 할인 정책을 적용한 가격을 반환하도록 한다.

 

 

 

 

 

앞선 Order 서비스에서는 Discount 서비스에  의존하지 않게 설계되었다.
단일 책임 원칙이 잘 지켜진 올바른 설계라고 볼 수 있다.

 

 

 

 

 

 

 

 

김영한 '스프링 핵심 원리 - 기본편' 강의를 기반으로 작성하였습니다.

https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8