[Spring-기본] 주문, 할인 도메인 수정

DANI·2023년 11월 22일

Spring[김영한T]

목록 보기
14/31
post-thumbnail

📑 비즈니스 요구사항 설계


📩 주문과 할인 정책

  • 회원은 상품을 주문할 수 있다.
  • 회원 등급에 따라 할인 정책을 적용할 수 있다.
  • 할인 정책은 모든 VIP는 1000원을 할인해주는 고정 금액 할인을 적용(나중에 변경 가능)
    👉 할인 정책은 변동가능성이 높으며, 최악의 경우 할인을 적용하지 않을 수 있다.

💡 정률할인정책으로 할인 정책 변경!



✅ 정률 할인 정책 구현체 생성

💾 RateDiscountPolicy 구현체 생성

package hello.core.Discount;

import hello.core.member.Grade;
import hello.core.member.Member;

public class RateDiscountPolicy implements DiscountPolicy{
    private int discountRate = 10;

    // 할인 금액
    @Override
    public int fixedDiscount(Member member, int price) {
        if(member.getGrade().equals(Grade.VIP)){
            return price * discountRate / 100;
        }else {
            return 0;
        }
    }
}


💾 RateDiscountPolicyTest 테스트 파일 생성

package hello.core.Discount;



import hello.core.member.Grade;
import hello.core.member.Member;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;


class RateDiscountPolicyTest {

    RateDiscountPolicy discountPolicy = new RateDiscountPolicy();

    @Test
    @DisplayName("VIP일 경우 10% 적용")
    void vipO() {
        Member member = new Member(1L, "홍길동", Grade.VIP);
        int rs= discountPolicy.fixedDiscount(member, 10000);
        Assertions.assertThat(rs).isEqualTo(1000);
    }

    @Test
    @DisplayName("VIP가 아닐 경우 10% 적용")
    void vipX() {
        Member member1 = new Member(2L, "이순신", Grade.Basic);
        int rs= discountPolicy.fixedDiscount(member1, 10000);
        Assertions.assertThat(rs).isEqualTo(0);
    }
}

🔴 실행결과

정률 할인 구현체를 완성하였다. 이제 OrderServiceImpl을 수정 해보자



✅ OrderServiceImpl 구현체를 수정

package hello.core.Order;

import hello.core.Discount.DiscountPolicy;
import hello.core.Discount.FixedDiscountPolicy;
import hello.core.Discount.RateDiscountPolicy;
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 FixedDiscountPolicy();
    private final DiscountPolicy discountPolicy = new RateDiscountPolicy();

    @Override
    public Order createOrder(Long id, String name, int price) {
        Member member = memberRepository.findById(id);
        int discount = discountPolicy.fixedDiscount(member, price);
        return new Order(id, name, price, discount);
    }
}


✅ 다음과 같이 구현체를 수정하였다.

  • private final DiscountPolicy discountPolicy = new FixedDiscountPolicy();

    👉 private final DiscountPolicy discountPolicy = new RateDiscountPolicy();



🚫 구현의 문제점

  • 역할과 구현을 분리했나? ⭕
  • 다형성도 활용하고, 인터페이스와 구현 객체를 분리했나? ⭕
  • OCP, DIP와 같은 객체지향 설계 원칙을 준수 했는가? ❌

🚫 DIP


: 주문서비스 구현체는 할인정책 인터페이스에 의존하면서 DIP를 지킨 것 처럼 보이나, 위 코드와 같이 구현체에도 함께 의존하고 있다.

🚫 OCP


: 위와 같이 코드를 변경하므로 OCP를 위반한다.


🔴 예상

🔍 주문 클래스 다이어그램

🔍 회원 클래스 다이어그램


🔵 실제

🔍 주문 클래스 다이어그램

🔍 회원 클래스 다이어그램


💡 해결방안

🔑 아래와 같이 변경한다.

🔍 주문 클래스 다이어그램

🔍 회원 클래스 다이어그램


✅ OrderServiceImpl 구현체를 수정

💾 OrderServiceImpl 구현체

package hello.core.Order;

import hello.core.Discount.DiscountPolicy;
import hello.core.Discount.FixedDiscountPolicy;
import hello.core.Discount.RateDiscountPolicy;
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 FixedDiscountPolicy();
    // private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
    private DiscountPolicy discountPolicy;

    @Override
    public Order createOrder(Long id, String name, int price) {
        Member member = memberRepository.findById(id);
        int discount = discountPolicy.fixedDiscount(member, price);
        return new Order(id, name, price, discount);
    }
}


✅ 다음과 같이 구현체를 수정하였다.

  • private final DiscountPolicy discountPolicy = new RateDiscountPolicy();

    👉 private DiscountPolicy discountPolicy;



💾 OrderServiceImpl 구현체

package hello.core.member;

public class MemberServiceImpl implements MemberService{

    private MemberRepository memberRepository;

    @Override
    public void join(Member member) {
        memberRepository.save(member);
    }

    @Override
    public Member findByMember(Long memberId) {
        return memberRepository.findById(memberId);
    }
}


✅ 다음과 같이 구현체를 수정하였다.

  • private final MemberRepository memberRepository = new MemoryMemberRepository();

    👉 private MemberRepository memberRepository;




❓ 인터페이스를 의존하는 것으로 바꾸면 구현체가 없는데 어떻게 할인정책을 구현할까?

0개의 댓글