오브젝트 #4

문승현·2022년 10월 7일
0

BeDev_4

목록 보기
5/5
post-thumbnail

이전 장에서 설계 시, 객체의 상태가 아닌 행동에 초점을 맞추어야 한다고 하였다.
상태(데이터)에 집중할 경우, 객체의 내부 구현을 외부에 노출시킬 수 있기 때문이다.
4장에서는 영화 예매 시스템을 데이터 중심으로 설계하여, 기존 설계와의 차이점을 살펴보았다.

객체지향 설계에서는 아래와 같이 2가지 방식으로 시스템을 구성할 수 있다.

1) 상태(데이터)를 중심으로
2) 행동(책임)을 중심으로

데이터 중심의 관점에서 객체는 데이터를 조작하는데 필요한 오퍼레이션(행동)을 정의한다.
책임 중심의 관점에서 객체는 오퍼레이션(행동)을 위해 필요한 상태를 저장한다.

다음과 같이 Movie 클래스를 정의해보자.

public class Movie
{
	private string title;
  	private Duration runningTime;
  	private Money fee;
  
  	private List<DiscountCondition> discountConditions;
	private Money discountAmout;
  	private double discountPercent;
	private MovieType movieType;
}

기존 설계와 다른 점은 할인 조건 목록인 discountConditions를 인스턴스 변수로서
Movie 클래스 안에 직접 정의하고 있다는 것이다.

public class DiscountCondition
{
	private DiscountConditionType type;
  	private int sequence;
  	private DayOfWeek dayOfWeek;
  	private DateTime startTime;
  	private DateTime endTime;
}

pubilc enum DiscountConditionType
{
	SEQUENCE,
    PERIOD
}

또한, DiscountPolicy라는 별도의 클래스로 분리했던 이전 설계와 달리,
할인 금액(discountAmount)과 할인 비율(discountPercent)을 Movie 내부에 정의하고 있다.
마지막으로 영화 별로 단 하나의 할인 정책을 지정해야 하기에 MovieType을 정의하고 있다.

public enum MovieType
{
	AMOUNT_DISCOUNT;
  	PERCENT_DISCOUNT;
  	NONE_DISCOUNT;
}

또한, 모든 인스턴스 변수의 접근 제어자가 private이기에 이를 조작하기 위해서는
각 인스턴스 별로 getter와 setter 메소드 역시 필요하다.

이러한 설계를 가지고 영화 예매 시스템을 구현하면 아래와 같다.
요약하자면 ReservationAgency는 반복문을 통해 할인 가능 여부를 확인하고,
할인 정책에 따라 예매 요금을 계산하여 예매를 진행한다.

public class ReservationAgency
{
	public Reservation Reserve(Screening screening, Customer customer, int audienceCount)
  	{
    	Movie movie = screening.GetMovie();
      	bool Discountable = false;
      	Money fee;
      	
      	foreach (var condition in movie.GetDiscountConditions())
        {
			if (condition.GetType() == DiscountConditionType.PERIOD)
            {
              	discountable = screening.GetWhenScreened()
                  						.GetDayOfWeek().Equals(conditions.GetDayOfWeek()) && 
              				condition.GetStartTime()
                  					.CompareTo(screening.GetWhenScreened().ToLocalTime()) <= 0 &&
							condition.GetEndTime()
              						.CompareTo(screening.GetWhenScreened().ToLocalTime()) >= 0;
            }
          	else 
            {
              	discountable = condition.GetSequence() == screening.GetSequence();
            }
          
          	if (discountable)
            {
              	break;
            }
        }
      
      	if (discountable)
        {
          	var discountAmount = Money.ZERO;
          	
          	switch (movie.GetMovieType())
            {
              case AMOUNT_DISCOUNT:
              	discountAmount = movice.GetDiscountAmount();
                break;
              case PERCENT_DISCOUNT:
                discountAmount = movice.GetFee().Times(movie.GetDiscountPercent());
                break;
              case NONE_DISCOUNT:
                discountAmount = Money.ZERO;
                break;
            }
          	
          	fee = movie.GetFee().Minus(discountAmount).Times(audienceCount);
        }
      	else 
        {
          	fee = movie.GetFee().Times(audienceCount);
        }
      
      	return new Reservation(customer, screening, fee, audienceCount);
    }
}

이제 해당 시스템이 책임 중심 설계에 기반한 시스템과 비교해 어떤 장단점이 있는지 살펴보자.

0개의 댓글