본문 바로가기

Java/객체지향

(OOP) 객체, 설계

초대장

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 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;
    }
}

관객

public class Audience {
    private Bag bag;

    public Audience(Bag bag) {
        this.bag = bag;
    }

    public Bag getBag() {
        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 Theater {
    private 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);
        }
    }
}

판매원

public class TicketSeller {
    private TicketOffice ticketOffice;

    public TicketSeller(TicketOffice ticketOffice) {
        this.ticketOffice = ticketOffice;
    }

    public TicketOffice getTicketOffice() {
        return ticketOffice;
    }
}

 

소프트웨어 모듈의 세가지 목적

1. 실행중에 제대로 동작하는 것 

2. 목적은 변경을 위해 존재하는 것 - 변경하기 어려운 모듈은 제대로 동작하더라도 개선해야한다.

3. 코드를 읽는 사람과 의사소통하는 것 - 개발자가 쉽게 읽고 이해할 수 있어야 한다.

 

현재코드는 2, 3 번을 만족하지 못한다. 왜일까?

 

소극장

public class Theater {
    private 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);
        }
    }
}

 

현재 소극장관람객의 가방을 열어 초대장이 들어있는지 살펴본다.

가방안에 초대장이 들어 있으면 판매원은 매표소에 보관돼 있는 티켓을 관람객의 가방 안으로 옮긴다.

가방안에 초대장이 들어 있지 않다면 관람객의 가방에서 티켓 금액만큼의 현금을 꺼내 매표소에 보관돼 있는 티켓을 관람객의 가방 안으로 옮긴다.

 

관람객과 판매원이 소극장의 통제를 받는 수동적인 존재이다.

하나의 클래스에 너무 많은 세부사항을 다루기 때문에 코드를 이해하는데 부담이 된다.

관객과 판매원을 변경할 경우 소극장도 변경해야된다.

 


코드개선 1

자율성 높이기 : 관객과 판매원을 자율적인 존재로 만들자

 

현재 소극장 

해당 내용을 판매원에 위임해보자

 

판매원 수정 

public class TicketSeller {
    private TicketOffice ticketOffice;

    public TicketSeller(TicketOffice ticketOffice) {
        this.ticketOffice = ticketOffice;
    }
    
/*getTicketOffice 제거*/
//    public TicketOffice getTicketOffice() {
//        return ticketOffice;
//    }

    public void sellTo(Audience audience) {
        if (audience.getBag().hasInvitation()) {
            //Ticket ticket = ticketSeller.getTicketOffice().getTicket();
            Ticket ticket = ticketOffice.getTicket();
            audience.getBag().setTicket(ticket);
        } else {
            //Ticket ticket = ticketSeller.getTicketOffice().getTicket();
            Ticket ticket = ticketOffice.getTicket();
            audience.getBag().minusAmount(ticket.getFee());
            //ticketSeller.getTicketOffice().plusAmount(ticket.getFee());
            ticketOffice.plusAmount(ticket.getFee());
            audience.getBag().setTicket(ticket);
        }
    }
}

getTicketOffice가 제거되었다.

외부에서는 ticketOffice에 접근할떄는 TicketOffice 에서만 접근이 가능하다.

TicketSeller는 ticketOffice에서 티켓을 꺼내거나 판매요금을 적립하는 일을 스스로 수행할 수 밖에 없다.

 


참고문헌

오브젝트
국내도서
저자 : 조영호
출판 : 위키북스 2019.06.17
상세보기