Spring 예제(3) 주문과 할인 도메인 설계

woohee·2024년 3월 28일

Spring 핵심원리

목록 보기
5/12
post-thumbnail

🔖지난 시간에 이어 더 복잡한 도메인을 설계해보자.


주문과 할인 도메인 설계

  • 주문과 할인 정책

    회원은 상푼을 주문 가능
    회원 등급에 따라 할인 정책을 적용 가능
    할인 정책은 모든 vip는 1000원을 할인해주는 고정 금액 할인을 적용(나중에 변경 가능)
    할인 정책은 변경 가능성이 높다. 할인을 적용하지 않을 수도 있다.(미확정)

주문 도메인 협력, 역할, 책임

  • 주문 생성 : 클라이언트는 주문 서비스에 주문 생성을 요청
  • 회원 조회 : 할인을 위해서는 회원등급이 필요하다. 그래서 회원 저장소에서 회원을 조회
  • 할인 적용 : 주문 서비스는 회원 등급에 따른 할인 여부를 할인 정책에 위임
  • 주문 결과 반환 : 주문 서비스는 할인 결과를 포함한 주문 결과를 반환

주문 도메인 전체

역할과 구현을 분리 자유롭게 구현 객체를 조립할 수 있도록 설계하였다.
회원 저장소와 할인 정책을 유연하게 변경할 수 있다.

주문 도메인 클래스 다이어그램

주문 도메인 객체 다이어그램1

주문 도메인 객체 다이어그램2

역할들의 협력 관계를 그대로 재사용할 수 있다.

주문과 할인 도메인 개발

discount, order 폴더 생성
discount

  • DiscountPolicy.java(interface)
  • FixDiscountPolicy.java(interface 구현)

order

  • Order.java
  • OrderService.java(interface)
  • OrderServiceImpl.java(interface 구현)

DiscountPolicy.java(interface)

할인정책을 정의하는 인터페이스이다.
위의 다이어그램을 참고하면 정액할인정책과 정률할인정책이 존재할 수 있다.
하지만 우리는 주문 객체 도메인1 대로 개발할 것이므로 정액할인정책만 사용하겠다.

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

FixDiscountPolicy.java(interface 구현)

할인정책을 구현하는 클래스로, 정액할인정책을 구현할 것이다.

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

Order.java

주문 객체를 생성하는 클래스. 즉, 주문을 생성하는 클래스이다.

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 calculatorPrice(){
        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 +
                '}';
    }
}

OrderService.java(interface)

주문서비스 메서드를 생성하는 인터페이스이다.
주문서비스는 주문을 생성한다.

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

OrderServiceImpl.java(interface 구현)

주문을 생성하는 메서드를 구현하는 인터페이스

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

실행 및 테스트

실행

public class OrderApp {

    public static void main(String[] args) {
        MemberService memberService = new MemberServiceImpl();
        OrderService orderService = new OrderServiceImpl();

        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "itemA", 10000);

        System.out.println("order=" + order);
        System.out.println("order.calculate= "+order.calculatorPrice());
    }
}

실행시켜보면 주문 조회가 가능하고 할인이 적용된 금액을 확인할 수 있다.

테스트

public class OrderServiceTest {
    MemberService memberService = new MemberServiceImpl();
    OrderService orderService = new OrderServiceImpl();

    @Test
    void createOrder(){
        Long memberId = 1L;
        Member member = new Member(memberId, "memberA", Grade.VIP);
        memberService.join(member);

        Order order = orderService.createOrder(memberId, "itemA", 10000);
        Assertions.assertThat(order.getDiscountPrice()).isEqualTo(1000);
    }
}

테스트코드도 만들어서 실행시켜보자.


🔖Summary

  • 회원 도메인에 이어 할인, 주문 도메인 설계 및 개발
  • 역할과 구현을 나눠서 구현하기

0개의 댓글