메세지? 메서드?
각 객체간에 협력하여 메서드를 실행하는게 메세지를 전송한다라고 한다.
이때, 인터페이스를 사용하여 메서드를 실행하게 되면, 클라이언트는 메서드가 자세히 어떻게 구현되어 있는지 모른다.
그래서 메서드 실행보다는, 오퍼레이션 호출이라고 부르는 것.
마치 챕터 2장의 코드중에, screen 객체가 movie 객체에게 영화비를 계산하라 라는 메세지를 던지는것과 같다.
인터페이스로 구현된거는 movie 객체가 할인금액을 계산하라 라는 메세지를 DiscountPolicy 객체에게 메세지를 던지는것 과 같다. 이때, 컴파일 시점에서는 movie객체가 Discountpolicy 객체의 할인 금액을 계산하라는 메서드에 자세히 어떻게 구현되어 있는지 모르기 때문에, 오퍼레이션이라고 한 것임.
퍼블릭 인터페이스 잘 만들기
디미터 법칙?
이거 만든 사람이 디미터라는 프로젝트 진행하다가 객체끼리 . 많이 쓰면 서로 의존성이 높은 코드 작성하게 된다고 해서 법칙으로 만듬
아래 조건을 만족하는 인스턴스만 메세지를 보내라
this 객체, 메서드의 매개변수, this 의 속성, this의 속성인 컬렉션의 요소, 메서드 내에서 생성된 지역 객체
-> . 많이 쓰지말기!
4장의 ReservationAgency 객체는 절차지향적이고 의존성이 많다.
원래는 screening.getMoive().calculateFee() 였음 (이렇게 작성하지 말라는 뜻~~~)
메서드내에서 생성된 지역 객체인 screening.calculateFee()를 사용해서 의존성을 낮춤
어떻게 하는지 말고 무엇을 하는데 집중하기
public class periodDiscountPolicy {
public boolean isPeriodSatisfied(){
....
}
}
이 코드보면 메서드에 어떻게 하는지 즉, 할인기간에 해당하는지의 메서드를 담고 있음.
무엇을 하는지에 집중하자
할인정책이 만족하는지? 로 변경하면 어떨까?
그러면 인터페이스로 구현을 하고 classname이 어떻게 할지를 설명한다면, 동일한 메서드 이름을 유지하면서도, 다양한 어떻게 할인할지의 할인정책을 많이 만들 수 있을꺼다.
public interface DiscountPolicy {
(abstract) public boolean isSatisfied();
}
public class PeriodDiscountPolicy implements DiscountPolicy{
@Override
public boolean isSatified(){
// 할인 만족하는지의 코드
}
}
예제를 통해서 캡슐화 진행
챕터 6의 step 1코드의 Theater 코드이다.
디미터 법칙을 위반하고 있다.
theater 객체에서 audience.getbag().has... .이 너무 많고 this나 매개변수의 객체 이외의 객체를 불러와서 사용하고 있다.
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);
}
}
}
개선해보자~
ticketSeller 에게 setTicket 권한을 주었다.
내부를 살펴보면, ticketSeller가 관객에게 초대권을 달라고 하고
관객은 가방에서 티켓을 꺼내고 가방은 유효한 초대권인지 확인하여 초대권을 준다.
(자세한건 실제 코드 살펴보자 한번에 이해가능하다.)
public void enter(Audience audience) {
ticketSeller.setTicket(audience);
}
step 3코드는
ticketSeller.setTicket(), Audience.setTicket(), bag.setTicket() 메서드 명이 의도를 제대로 전달하지 못하니까
메서드명을
ticketSeller.sellTo(), Audience.buy(), bag.hold() 로 표시했다.
디미터 법칙 반드시 지켜야함?
절대적인 법칙은 없음 예를 들어, 이런 코드가 있다고 하면,
Screen객체에서 다시 ScreenTime 객체를 다시 가져와서 할인기간을 판단하기 때문에, 디미터 법칙이 위배되어 Screen 객체로 로직을 옮겨서 메서드를 만들어야하는거 아닌가? 라는 의문점이 들 수 있다.
하지만, Screen이 할인조건을 판단하는 책임을 가져가 버리기 때문에, 코드의 의도가 불분명해질 수 있다.
트레이드 오프를 생각하며 캡슐화를 하자!
public class PeriodDiscountPolicy implements DiscountPolicy{
@Override
public boolean isSatified(Screen sc){
return sc.getScreenTime().getDateOfWeek() >= 24 ~~~~;
}
}
'오브젝트' 카테고리의 다른 글
5장 책임을 할당하기 (0) | 2025.01.07 |
---|---|
4장 설계품질과 트레이드 오프 (0) | 2025.01.03 |
3장 역할, 책임, 협력 (0) | 2024.12.27 |
2장 객체지향 프로그래밍 (1) | 2024.12.13 |