1. 컴파일 시간 의존성과 실행 시간 의존성
1-1) DiscountPolicy 상속 계층 Image
AmountDiscountPolicy(금액할인정책)과 PercentDiscountPolicy(기간할인정책)
이처럼 어떤 클래스가 다른 클래스에 접근할 수 있는 경로를 가지거나
해당 클래스의 객체 메서드를 호출할 경우 두 클래스 사이에 의존성이 존재한다고 말한다.
1-2) 의존성 구분
Movie의 객체는 실행 시에 AmountDiscountPolicy나 PercentDiscountPolicy의 객체에 의존할
수밖에 없는 상황이 생기는데, 코드 수준에서 Movie 클래스는 두 클래스 중 어떤 것에도
의존하지 않는다. 오직 추상 클래스인 DiscountPolicy에만 의존하고 있다.
1-3) Movie의 객체가 실행시점에 알게 되는 AmountDiscountPolicy와 PercentDiscountPolicy
1-3)-1. Movie의 금액할인 정책일 때
/* Movie 객체 생성시 받아야할 값들.
(String title, Duration runningTime, Money fee,
DiscountPolicy discountPolicy)
*/
Movie avatar = new Movie("아바타", Durantion.ofMinutes(120),
Money.wons(10000), new AmountDiscountPolicy(Money.wons(800), ...));
1-3)-2. Movie의 비율할인 정책일 때
/* Movie 객체 생성시 받아야할 값들.
(String title, Duration runningTime, Money fee,
DiscountPolicy discountPolicy)
*/
Movie avatar = new Movie("아바타", Durantion.ofMinutes(120),
Money.wons(10000), new PercentDiscountPolicy(0.1, ...));
1-3)-3. Movie의 의존성
코드 상에서 Movie는 DiscountPolicy에 의존한다. 코드를 조사해도 Movie가
AmountDiscountPolicy나 PercentDiscountPolicy에 의존하는 곳을 찾을 수 없다.
실행 시점에는 Movie의 객체는 AmountDiscountPolicy나
PercentDiscountPolicy의 객체에 의존하게 된다.
여기서 중요한 포인트는 코드의 의존성과 실행시점의 의존성이 서로 다를 수 있다는 거임.
다시 말해, 클래스 사이의 의존성과 객체 사이의 의존성은 동일하지 않을 수 있다.
그리고 유연하게 재사용할 수 있으며 확장 가능한 객체지향 설계가 가지는 특징은
코드의 의존성과 실행 시점의 의존성이 다르다는 거임.
설계가 유연해질수록
유연성을 억제하면
코드를 이해하고 디버깅하기는 쉬워지지만 재사용성과
확장 가능성은 낮아진다는 사실도 기억하기
2. 다형성
2-1) 메시지
Movie는 DiscountPolicy의 객체에게 calculateDiscountAmout 메시지를 전송한다.
실행되는 메서드는 Movie와 상호작용하기 위해 연결된 객체의 클래스가 무엇인가에 따라 달라진다.
AmountDiscountPolicy의 객체라면
PercentDiscountPolicy의 객체라면
코드 상에서 Movie 클래스
2-2) 인터페이스와 다형성 Image
3. 추상화
3-1) 추상화의 힘 Image
추상화를 사용할 경우의 두 가지 장점을 보여준다. 첫 번째 장점은 추상화의 계층만 따로 떼어 놓고
살펴보면 요구사항의 정책을 높은 수준에서 서술할 수 있다는 거임.
두 번째 장점은 추상화를 이용하면 설계가 좀 더 유연해진다는 거임.
하나의 문장으로 정리하면
포괄적인 문장
영화 예매 요금은 ‘금액할인 정책’과 ‘두 개의 순서 조건, 한 개의 기간 조건’을 이용해
계산할 수 있다.
4. 좀 더 유연한 설계
4-1) Movie class
4-2) NoneDiscountPolicy class
4-3) 객체 생성
// Movie
public Movie(String title, Duration runningTime, Money fee,
DiscountPolicy discountPolicy) {
this.title = title;
this.runningTime = runningTime;
this.fee = fee;
this.discountPolicy = discountPolicy;
}
Movie starWars = new Moive(
"스타워즈", Duration.ofMinutes(210),
Money.wons(10000),
// 새로운 클래스를 추가한 것만으로 애플리케이션의 기능을 확장했음.
new NoneDiscountPolicy()
);
4-4) 추상화 설계가 가능한 이유
설계가 구체적인 상황에 결합되는 것을 방지하기 때문이다.
Moive(영화)
Movie는 특정한 할인 정책에 묶이지 않았다.
할인 정책을 구현한 클래스가 DiscountPolicy를 상속 받고 있다면
어떤 클래스와도 협력이 가능함.
DiscountPolicy(할인정책)
특정한 할인 조건에 묶이지 않았다. DiscountCondition을 상속받은 어떤 클래스와도
협력이 가능함. 컨텍스트 독립성이라고 불리는 이 개념은 프레임워크와 같은 유연한 설계가
필수적인 분야에서 그 진가를 발휘 함.