import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args){
// 영화관 + 티켓오피스 + 티켓판매자 생성
Theater theater = generateTheater();
// 관람객 생성
List<Audience> audienceList = generateAudience();
System.out.println("============================");
System.out.println("고객 두분이 오셨습니다.");
for(Audience audience : audienceList)
theater.enter(audience);
System.out.println("============================");
System.out.println("고객이 상영관에 들어갑니다.");
}
public static Theater generateTheater(){
//티켓오피스 100만원 + 10개 티켓 넣어준다.
//티켓판매자를 티켓오피스에 배정
List<Ticket> ticketList = generateTicket();
TicketOffice ticketOffice = new TicketOffice(1000000l, ticketList);
TicketSeller ticketSeller = new TicketSeller(ticketOffice);
System.out.println("영화관 + 티켓오피스 + 티켓판매자 생성 완료...");
return new Theater(ticketSeller);
}
public static List<Ticket> generateTicket(){
List<Ticket> ticketList = new ArrayList<>();
for(int i=1;i<10;i++){
Ticket ticket = new Ticket();
ticket.setTitle("왕의남자");
ticket.setFee(10000l);
ticketList.add(ticket);
}
System.out.println("티켓 생성 완료...");
return ticketList;
}
public static List<Audience> generateAudience(){
//초대장은 어느영화인지 상관없고 날짜만 해당하면 입장가능
LocalDateTime localDateTime = LocalDateTime.of(20,12,25,20,00);
Invitation invitation = new Invitation(localDateTime);
List<Audience> audienceList = new ArrayList<>();
//초대장 있는 회원
Bag bag1 = new Bag(invitation,50000l);
Audience audience1 = new Audience();
audience1.setBag(bag1);
audienceList.add(audience1);
//초대장 없는 회원
Bag bag2 = new Bag(50000l);
Audience audience2 = new Audience();
audience2.setBag(bag2);
audienceList.add(audience2);
System.out.println("관람객 2명 생성 완료...");
return audienceList;
}
}
import com.larrykim.chap01.Audience;
public class Theater {
public TicketSeller ticketSeller;
public Theater(TicketSeller ticketSeller){
this.ticketSeller=ticketSeller;
}
public void enter(Audience audience) {
// 문제점: 고객 가방에서 초대장 직접 확인 하네... 고객이 하게 해줘도 될텐데...
if (audience.getBag().hasInvitation()) {
// 문제점: 티켓판매자가 속한 티켓오피스에서 직접 티켓을 가져온다고...!?
Ticket ticket = ticketSeller.getTicketOffice().getTicket();
// 문제점: 손님 가방에 직접 티켓을 챙겨주네...
audience.getBag().setTicket(ticket);
} else {
Ticket ticket = ticketSeller.getTicketOffice().getTicket(); // 문제점: 위와 동일
audience.getBag().minusAmount(ticket.getFee()); // 문제점: 위와 동일
ticketSeller.getTicketOffice().plusAmount(ticket.getFee()); // 문제점: 위와 동일
audience.getBag().setTicket(ticket); // 문제점: 위와 동일
}
}
//2 변경이 용이하지 않을 것이다.
// 관람객과 티켓판매원(Audience, TicketSeller) 클래스를 변경할 경우 Theater도 변경해야 된다.
// 예를들어, 고객이 가방을 들고 있지 않다면 어떻게 해야 할까?
// 또 현금이 아니라 신용카드를 이용해서 결제한다면?
// Audience의 내부에 대해 더 많이 알면 알수록 Audience를 변경하기 어려워진다. (의존성 문제)
//3 코드를 읽는 사람과 의사소통되어야 한다.
// 이해하기 어려운 이유는,
// Theater의 enter 메서드를 이해하기 위해서는 Audience가 Bag을 가지고 있고,
// Bag 안에는 현금과 티켓이 들어 있으며 Ticketseller가 Ticketoffice에서 티켓을 판매하고,
// Ticketoffice 안에 돈과 티켓이 보관돼 있다는 모든 사실을 기억하고 있어야 한다.
// 로버트 마틴 3가지 목적에 불만족...
}
public class Theater {
public TicketSeller ticketSeller;
//...
public void enter(Audience audience) {
//무전기로 손님 갑니다. 메시지 전달.
ticketSeller.sellTo(audience);
}
}
------------------------------------------------------------------------
public class TicketSeller {
private TicketOffice ticketOffice;
//...
public void sellTo(Audience audience) {
System.out.println("Before");
System.out.println("보유티켓수 = "+ticketOffice.getTicketCount());
System.out.println("보유금액 = "+ticketOffice.getAmount());
System.out.println("=============");
ticketOffice.plusAmount(audience.buy(ticketOffice.getTicket()));
System.out.println("=============");
System.out.println("After");
System.out.println("보유티켓수 = "+ticketOffice.getTicketCount());
System.out.println("보유금액 = "+ticketOffice.getAmount());
}
}
------------------------------------------------------------------------
public class Audience {
//...
public Long buy(Ticket ticket) {
if (bag.hasInvitation()) { //본인이 직접 가방 확인.
System.out.println("1 손님: 초대장이 있어요^^!");
bag.setTicket(ticket);
return 0L; //초대장이 있으니 돈줄 필요 x
} else {
System.out.println("2 손님: 초대장이 없어요ㅜㅜ");
System.out.printf("2 손님: 제가방에서 %d원을 감소시키고 돈을 전달할게요.\n",ticket.getFee());
bag.setTicket(ticket);
bag.minusAmount(ticket.getFee());
return ticket.getFee();
}
}
}
public class Bag {
private Long amount;
private Invitation invitation;
private Ticket ticket;
public Bag(Long amount){
this(null, amount);
}
public Bag(Invitation invitation, Long amount){
this.invitation=invitation;
this.amount=amount;
}
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;
}
}
------------------------------------------
package org.eternity.theater.step03;
public class Bag {
private Long amount;
private Ticket ticket;
private Invitation invitation;
public Long hold(Ticket ticket) {
if (hasInvitation()) {
setTicket(ticket);
return 0L;
} else {
setTicket(ticket);
minusAmount(ticket.getFee());
return ticket.getFee();
}
}
private void setTicket(Ticket ticket) {
this.ticket = ticket;
}
private boolean hasInvitation() {
return invitation != null;
}
private void minusAmount(Long amount) {
this.amount -= amount;
}
}
//...
public Long buy(Ticket ticket) {
if (bag.hasInvitation()) {
bag.setTicket(ticket);
return 0L;
} else {
bag.setTicket(ticket);
bag.minusAmount(ticket.getFee());
return ticket.getFee();
}
}
//...
------------------------------------------
//...
public Long buy(Ticket ticket) {
return bag.hold(ticket);
}
//...