[오브젝트 : 코드로 이해하는 객체지향 설계] 2. 객체지향 프로그래밍
2021. 8. 17. 00:39ㆍ오브젝트 : 코드로 이해하는 객체지향 설계
영화 예매 프로그램
이 글에서 영화와 상영의 개념
- 영화 : 영화에 대한 기본 정보 → 상영시간, 가격, 제목 등
- 상영 : 실제로 관객들이 영화를 관람하는 것 → 상영 일자, 시간 등
할인
- 할인 조건(discount condition)
- 순서 조건
- 기간 조건
- 할인 정책(discount policy)
- 금액 할인
- 비율 할인
클래스가 아닌 객체
먼저 객체들의 공통된 특성과 상태를 가진 객체들을 분류하고 이것을 기반으로 클래스를 구현해야 한다.
도메인
문제를 해결하기 위해 사용자가 프로그램을 사용하는 분야
영화를 좀 더 쉽고 빠르게 예매하려는 사용자의 문제 → 영화 예매 시스템
클래스 구현하기
public class Screening {
private Movie movie;
private int sequence;
private LocalDateTime whenScreened;
public Screening(Movie movie, int sequence, LocalDateTime whenScreened) {
this.movie = movie;
this.sequence = sequence;
this.whenScreened = whenScreened;
}
public LocalDateTime getStartTime() {
return whenScreened;
}
public boolean isSequence(int sequence) {
return this.sequence == sequence;
}
public Money getMovieFee() {
return movie.getFee();
}
public Reservation reserve(Customer customer, int audienceCount) {
return new Reservation(customer, this, calculateFee(audienceCount), audienceCount);
}
private Money calculateFee(int audienceCount) {
return movie.calculateMovieFee(this).times(audienceCount);
}
}
변수는 private로 객체의 속성에 직접 접근할 수 없도록 하고 적절한 public 메서드를 통해서 내부 상태를 변경 할 수 있게 해야한다.
할인 요금 구하기
public class Movie {
private String title;
private Duration runningTime;
private Money fee;
private DiscountPolicy discountPolicy;
public Movie(String title, Duration runningTime, Money fee, DiscountPolicy discountPolicy) {
this.title = title;
this.runningTime = runningTime;
this.fee = fee;
this.discountPolicy = discountPolicy;
}
public Money getFee() {
return fee;
}
public Money calculateMovieFee(Screening screening) {
// interface인 discountPolicy에 calculateDiscountAmount 메시지를 전송한다.
// -> 할인 요금을 반환 받는다.
// Movie는 기본 요금인 fee에서 반환된 할인 요금을 차감한다.
return fee.minus(discountPolicy.calculateDiscountAmount(screening));
}
}
해당하는 상영 정보에 맞는 요금 할인 정책에 따라서 할인 금액을 계산하고, 기본 요금에서 할인 요금을 차감한다.
할인 정책과 할인 조건
할인 정책은 할인 요금을 계산하는 방식만 다르기 때문에 중복 코드를 제거하기 위해 공통 코드를 보관하는 DiscountPolicy 클래스를 작성한다.
public abstract class DiscountPolicy {
private List<DiscountCondition> conditions = new ArrayList<>();
public DiscountPolicy(DiscountCondition ... conditions) {
this.conditions = Arrays.asList(conditions);
}
public Money calculateDiscountAmount(Screening screening) {
for(DiscountCondition each : conditions) {
if(each.isSatisfiedBy(screening)) {
return getDiscountAmount(screening);
}
}
return Money.ZERO;
}
abstract protected Money getDiscountAmount(Screening screening);
}
calculateDiscountAmount 메서드는 상영이 할인 조건을 만족하면 getDiscountAmount 메서드를 호출해서 할인 요금을 계산하고 조건에 만족하는 할인 조건이 없으면 원래의 영화 가격을 반환한다.
실제로 getDiscountAmount메서드는 자식 클래스에서 오버라이딩한 메서드가 실행된다.
부모 클래스에 기본적인 흐름을 구현하고 중간에 필요한 처리를 자식 클래스에게 위임하는 디자인 패턴을 TEMPLATE METHOD 패턴 이라고 한다.
합성
인터페이스에 정의된 메시지를 통해서만 코드를 재사용하는 방법
상속의 큰 문제점 : 캡슐화를 위반(강결합)
반응형
'오브젝트 : 코드로 이해하는 객체지향 설계' 카테고리의 다른 글
[오브젝트 : 코드로 이해하는 객체지향 설계] 6. 메시지와 인터페이스 (0) | 2021.09.08 |
---|---|
[오브젝트 : 코드로 이해하는 객체지향 설계] 5. 책임 할당하기 (0) | 2021.09.02 |
[오브젝트 : 코드로 이해하는 객체지향 설계] 3. 역할, 책임, 협력 (0) | 2021.08.24 |
[오브젝트 : 코드로 이해하는 객체지향 설계] 1. 객체, 설계 (0) | 2021.08.11 |