새로운 할인 정책을 적용을 해보았다.

 

package hello.core.order;

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

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

문제점이 발견되었다.

 

할인정책을 변경하려면 클라이언트인 OrderServiceImpl 코드의 수정이 필요하다.

 

역할과 구현을 충실하게 분리하였고,

다형성도 활용하고, 인터페이스와 구현객체를 분리했지만

OCP, DIP와 같은 객체지향 설계원칙을 준수한 것처럼 보이지만

사실은 아니다.

 

먼저 DIP 관점에서

OrderServiceImpl는 DiscountPolicy 인터페이스에 의존하면서

DIP를 지킨 것 같지만 

클래스 의존관계를 분석해보면 추상(인터페이스) 뿐만 아니라 구체(구현) 클래스에도 의존하고 있다.

추상 의존 : DiscountPolicy

구체 클래스 : FixDiscountPolicy , RateDiscountPolicy

그렇기에 DIP 위반!

 

OCP 관점에서 

FixDiscountPolicy를 RateDiscountPolicy로 바꾸는 순간

코드의 변경이 일어난다. 

그렇기에 OCP 위반!

 


 

이 문제를 어떻게 해결할 수 있을까??

 

클라이언트 코드인 OrderServiceImpl은 DiscountPolicy의 인터페이스 뿐만 아니라 

구체 클래스도 함꼐 의존한다.

그래서 구체 클래스를 변경할때 클라이언트 코드도 함께 변경해야 한다.

DIP를 위반하지 않도록 인터페이스에만 의존하도록 의존관계를 변경해야 한다.

 

package hello.core.order;

import hello.core.discount.DiscountPolicy;
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 DiscountPolicy discountPolicy;
    
    @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);
    }
}

인터페이스에만 의존하도록 코드를 변경해 보았다

그런데 구현체가 없는데 어떻게 코드를 실행할까?

실제 실행을 해보면 널포인트익셉션이 발생한다.

 

이 문제를 해결하려면 누군가가 클라이언트인  OrderServiceImpl에 DiscountPolicy의 구현

객체를 대신 생성하고 주입해주어야 한다.

+ Recent posts