오브젝트 1장 - 객체, 설계 (1) 티켓 판매 어플리케이션 구현

YeongJun Son·2023년 4월 3일
0

오브젝트

목록 보기
1/2

들어가며

글과 관련해

  • 코드 내에서 쓰이는 주석은 제가 추가로 단 것입니다.
  • 모든 코드는 최하단 참고문헌에서 참고했습니다.

선요약 및 정리

  • 오브젝트의 부제는 "코드로 이해하는 객체지향 설계"입니다. 저자는 이론보다도 실무가 우선한다고 밝히며, 코드를 중심으로 '객체 지향'에 관해 살펴보기를 권합니다.
  • 1장 (1)에서는, 티켓 판매 애플리케이션이라는 예시를 들며, 각 객체가 갖는 속성(인스턴수 변수)과 기능(메서드)에 기반해 객체들을 구현합니다.
  • 제가 보기에, 중점은 단순히 구현에 있는 것이 아니라, 각 객체들이 서로 맺고 있는 관계를 살펴보는 것에 있습니다.

Ch 01. 객체, 설계 (1)

객체 지향에 있어 실무와 이론

  • 로버트 L 글래스; "이론이 먼저일까 실무가 먼저일까?"
  • 어떤 분야든 초기 단계: 아무것도 없는 상태
    → 이론을 정립하기보다는 실무를 관찰한 결과를 바탕으로 이론을 정립하는 것이 최선

01. 티켓 판매 애플리케이션 구현하기

기본 원리

  • 추첨을 통해 선정된 관람객에게 공연을 무료로 관람할 수 있는 초대장 발송
  • 이벤트에 당첨된 관람객과 그렇지 못한 관람객은 다른 방식으로 입장시켜야 한다

초대장 구현

  public class Invitation { // 초대 일자를 인스턴수 변수로 포함
    private LocalDateTime when;
 } 
  • 티켓에는 공연의 날짜가 적혀 있어야 합니다.

티켓 구현

 public class Ticket {
   private Long fee; // 클래스 내부에서만 접근
   
   public Long getFee() { // 클래스 외부에서 값 이용 가능
     return fee;
   }
}
  • 공연 관람은 티켓이 있어야만 가능합니다.

가방 구현

  public class Bag {
  	private Long amount;
  	private Invitation invitation;
  	private Ticket ticket;
  
    public boolean hasInvitation() { // 초대장 소지 여부
      return invitation != null;
    }
  
    public boolean hasTicket() { // 티켓 소지 여부
      return ticket != null;
    }
  
    public void setTicket(Ticket ticket) { // 티켓 설정
  	  this.ticket = ticket;
    }
  
    public void minusAmount(Long amount) { // 현금 감소
  	  this.amount -= amount;
    }
  
    public void plusAmount(Long amount) { // 현금 증가
  	  this.amount += amount;
    }
  }
  • 관람객이 소지품을 넣어두는 Bag 클래스는 현금(amount), 초대장(invitation), 티켓(ticket)을 인스턴스 변수로 포함합니다.

  • 이벤트 당첨자는 티켓으로 교환할 초대장을 가지고 있고, 미당첨자는 현금을 보유합니다. 티켓을 구매하거나 초대장과 교환하기 전, 초기 상태에는 두 가지 경우가 있습니다.

    1. 초대장이 있고, 현금도 있다. (이후 현금 양 상관 X)
    2. 초대장은 없고, 현금은 있다. (이후 현금 양 상관 O)

Bag 클래스에 생성자 추가

  public class Bag {
  	public Bag(long amount) { // 초대장 없음
  	  this(null, amount);
  	}
  
    public Bag(Invitation invitation, long amount) { // 초대장 있음
      this.invitation = invitation;
      this.amount = amount;
  	}
  } 
  • Bag의 인스턴스를 생성하는 시점에, 방금 살펴본 제약을 강제할 수 있도록 생성자를 추가합니다.

관람객 구현

  public class Audience { // 관람객은 가방을 소지
  	private Bag bag;
  
  	public Audience(Bag bag) {
  	  this.bag = bag;
  	}
  	
  	public Bag getBag() { // 외부에서 bag에 접근
  	  return bag;
  	}
  }
  • 관람객은 가방을 소지하고 있다.

매표소 구현

  public class TicketOffice {
  	private Long amount;
  	private List<Ticket> tickets = new ArrayList<>();
  
  	public TicketOffice(Long amount, Ticket ... tickets) {
  	  this.amount = amount;
  	  this.tickets.addAll(Arrays.asList(tickets));
  	}
  
  	public Ticket getTicket() { // 티켓을 주면서, 하나 제거
  	  return tickets.remove(0);
  	}
  
  	public void minusAmount(Long amount) { // 현금 감소
  	  this.amount -= amount;
  	}
  
  	public void plusAmount(Long amount) { // 현금 증가
	  this.amount += amount;
  	}
  }
  • 매표소에는 티켓과 금액이 보관되어 있다. 매표소는 자원을 보관하는 곳이다.

매표원 구현

  public class TicketSeller {
  	private TicketOffice ticketOffice;
  
  	public TicketSeller(TicketOffice ticketOffice) {
  	  this.ticketOffice = ticketOffice;
  	}
  
  	public TicketOffice getTicketOffice() {
      return ticektOffice;
  	}
  }
  • 매표원은 매표소에서 티켓을 교환해주거나 판매하는 역할을 한다. 즉, 매표소에 접근할 수 있어야 한다.

소극장 구현

  public class Theater {
  	private TicketSeller ticketSeller;
  
  	public Theater(TicketSeller ticketSeller) {
  	  this.ticketSeller = ticketSeller;
  	}
  
  	public void enter(Audience audience) {
  	  if (audience.getBag().hasInvitation()) { // 초대장 O, 교환
  		Ticket ticket = ticketSeller.getTicketOffice().getTIcket();
  		audience.getBag().setTicket(ticket);
  	  } else { // 초대장 X, 현금 받고 티켓 주기
  		Ticket ticket = ticketSeller.getTicektOffice().getTicket();
  		audience.getBag().minusAmount(ticekt.getFee());
  		ticketSeller.getTicketOffice.plusAmount(ticket.getFee());    			
        audience.getBag().setTicket(ticket);
  	  }
  	}
  }
  • 소극장은 관람객의 가방 안에 초대장이 들어 있는지를 조건으로, 만약 아니라면 현금이 충분한지를 조건으로 입장 여부를 결정한다

    1. 초대장이 있다면:
      이벤트에 당첨된 관람객
      → 티켓을 관람객의 가방 안에 넣어줌
    2. 초대장이 없다면:
      티켓을 판매해야 함
      → 관람객 금액 차감 후 매표소 금액 증가

그러나

  • 위 프로그램은 문제점을 가지고 있다. (2장에서 계속)

나가며

질문들

  • 만약 각 객체들이 스스로 숨기는 것 없이 쓰인다면, 왜 객체를 나누어야 하는가? 이런 경우에는 소극장 안에 다 넣는 것과 큰 차이가 없지 않나?
    1. 소극장과 매표원
    2. 소극장과 관람객의 가방
  • 매표소와 매표원을 '자동 매표 기계'라고 생각하면 더 간단해지지 않을까? 혹은 '자동 매표 기계'로 했을 때 문제점은 무엇일까?
    지금 생각나는 단점은, 클래스가 하나 더 줄어든다는 점에 비해서 1. 자원 저장 및 2. 티켓 교환 (자원 분배) 이라는 두 기능이 분리되지 않아 오히려 더욱 복잡한 구조를 만들 수 있다는 점이다.
profile
제가 좋아하는 것은 도가 아니라 기입니다

0개의 댓글