일관성 있는 협력 패턴을 적용하면 작성한 코드가 이해하기 쉽고 직관적이며 유연해진다.
11장에서 구현한 핸드폰 과금 시스템의 요금 정책을 수정하자. 기본 정책에는 일반 요금제와 심야 할인 요금제 두가지 가 있었다.
기본정책 4가지 방식
public class FixedFeePolicy extends BasicRatePolicy {
private Money amount;
private Duration seconds;
public FixedFeePolicy(Money amount, Duration seconds) {
this.amount = amount;
this.secound = seconds;
}
@Override
protected Money calculateCallFee(Call call) {
return amount.times(call.getDuration().getSeconds() / seconds.getSeconds());
}
}
시간대별 방식의 통화 요금을 계산하기 위해서는 통화의 시작 시간과 종료 시간 뿐만 아니라 시작 일자와 종료 일자도 함께 고려해야 한다.
public class DateTimeInterval {
private LocalDateTime from;
private LocalDateTime to;
public static DateTimeInterver of (LocalDateTime from, LocalDateTime to) {
return new DateTimeInterval(from, to);
}
public static DateTimeInterval toMidnight(LocalDateTime from) {
return new DateTimeInterval(
from ,
LocalDateTime.of(to.toLocalDate(), LocalTime.of(23,59,59));
}
public static DateTimeInterval fromMidnight(LocalDateTime to) {
return new DateTimeInterval(
LocalDateTime.of(to.toLocalDate(), LocalTime.of(0,0)),
to);
}
public static DateTimeInterval during(LocalDate date) {
return new DateTimeInterval (
LocalDateTime.of(to.toLocalDate(), LocalTime.of(0,0)),
LocalDateTime.of(to.toLocalDate(), LocalTime.of(23,59,59));
)
}
private DateTimeInterval(LocalDateTime from, LocalDateTime to) {
this.from = from;
this.to = to;
}
public Duration duration(){
return Duration.between(from, to);
}
public LocalDateTime getFrom(){
return from;
}
public LocalDateTime getTo(){
return to;
}
}
public class Call {
private DateTimeInterval interval;
public Call(LocalDateTime from, LocalDateTiem to) {
this.interval = DateTimeInterval.of(from, to);
}
public Duration getDuration(){
public interval.duration();
}
public LocalDateTime getFrom() {
return interval.getFrom();
}
public LocalDateTime getTo() {
return interval.getTo();
}
public DateTimeInterval getInterval(){
return interval;
}
}
요금 계산 로직은 크게 두 단계로 나뉜다.
기간을 처리하는 전문가는 DateTimeInterval이니 첫번째 로직은 DateTimeInterval에 위임한다.