할인정책(DiscountPolicy) 인터페이스에는
1. FixDiscountPolicy(고정할인)
2. RateDiscountPolicy(정률할인)
라는 구현체가 있다.
< DiscountPolicy > 인터페이스(역할)
public interface DiscountPolicy {
/**
* @return 할인 대상 금액
*/
int discount(Member member, int price);
}
할인정책은 여러가지가 있을 수 있다.
고정할인금액, 정률할인금액, ... 등등 앞으로도 할인방법은 계속 추가될 수 있으니 할인정책이라는 인터페이스를 구현하고 구현체를 만들어 할인정책 방법을 바꿔끼며 사용할 수 있다.
우선, FixDiscountPolicy 할인정책을 사용해보겠다.
< FixDiscountPolicy > 구현체
public class FixDiscountPolicy implements DiscountPolicy {
private int discountFixAmount = 1000; // 천원 할인
@Override
public int discount(Member member, int price) {
if (member.getGrade() == Grade.VIP) {
return discountFixAmount;
} else {
return 0;
}
}
}
위의 할인정책 방법을 사용하기 위해서는
주문 서비스에서 주입 받아야 한다.
< OrderServiceImple >
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
@Override
public Order creatOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
// 할인은 내 책임이 아님! 할인에 관한건 전부 dicountPolicy에 넘김 (회원 등급, 상품 가격)
// SRP(단일 책임 원칙) 잘 지켜짐
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
위의 코드처럼
private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
이러한 문장으로 FixDiscountPolicy 구현체를 주입받을 수 있다.
만약 할인정책이 고정할인에서 정률할인으로 바뀐다고 하더라도 구현체만 갈아끼우면 된다.
아래처럼 말이다!
private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
❓ 객체지향 설계 원칙 중 OCP, DIP를 잘 지키고 있는가? ❓
를 살펴보면 그렇지 않다는 것을 알 수 있다.
OrderServiceImpl에서 할인정책 인터페이스인 DiscountPolicy에만 의존하도록 코드를 변경하면,
public class OrderServiceImpl implements OrderService {
private final MemberRepository memberRepository = new MemoryMemberRepository();
// private final DiscountPolicy discountPolicy = new FixDiscountPolicy();
// private final DiscountPolicy discountPolicy = new RateDiscountPolicy();
private DiscountPolicy discountPolicy; // final은 값을 무조건 할당해야해서 제거, 구현체에 의존하지 않고 역할(인터페이스)에만 의존하는 중
@Override
public Order creatOrder(Long memberId, String itemName, int itemPrice) {
Member member = memberRepository.findById(memberId);
// 할인은 내 책임이 아님! 할인에 관한건 전부 dicountPolicy에 넘김 (회원 등급, 상품 가격)
// SRP(단일 책임 원칙) 잘 지켜짐
int discountPrice = discountPolicy.discount(member, itemPrice);
return new Order(memberId, itemName, itemPrice, discountPrice);
}
}
위처럼 변경할 수 있다.
"= new FixDiscountPolicy()"를 제거한 것이다.
이렇게 변경함으로써 DIP 위반을 해결하였는데, 이를 실행해보면 NullPointerException이 발생한다.
당연하다, DiscountPolicy는 인터페이스이고, 구현체를 지정해주지 않았는데 실행될 수 없다.