[인프런 워밍업 0기] Visitor Pattern 적용해보기!
이는 프로젝트 3단계를 해결하며, 새롭게 공부한 Visitor Patter에 대한 기록입니다.저는 연차 기록(LeaveRecord)과 출퇴근 기록(WorkRecord)을 근무 상태(AttendanceStatus)의 서브클래스로 상정했고, 추후에 출장이나 결근과 같이 상태가 확장될 수도 있다고 보았습니다.프로젝트 3단계, 요청 달의 연차 기록과 근무 기록을 모두 출력하는 기능을 구현하는데 있어 위의 도메인 구조는 다음과 같은 고려 사항이 있었습니다.요청 달의 모든 연차 기록과 근무 기록을 부모 클래스로 모두 호출한다.연차 사용여부를 근무를 한 일자에는 false로 하지만, 연차를 사용한 일자에는 true로 반환한다.저는 이 부분에 있어 다른 두 객체가 같은 결과를 내지만 처리 방식이 다른 경우라고 생각했습니다.그래서 이를 어떻게 해결할 지 인터넷을 뒤지다가 Visitor 패턴이라는 것을 발견하게 됩니다.Vistor 패턴Vistor 패턴은 서로 다른 상태를 가진 객체가 공통 로직을 수행해야 할 때 유용합니다.여러 객체의 공통 목표의 수행 방식이 다른 로직을 해당 객체가 아닌, Visitor라는 객체에게 위임합니다.이렇게 되면, 다음과 같은 이점이 발생합니다.객체는 자신과 관계성이 떨어지는 로직을 다른 객체에게 위임함으로써 응집도가 상승합니다.여러 객체가 공통 목표로 가진 로직이, Visitor 객체에게 집중됨으로써 관리가 용이해집니다.기존 설계를 크게 해치지 않고, 다양한 로직을 추가할 수 있습니다. Visitor 패턴을 사용하기 위해서는 2가지가 필요합니다.객체들이 Visitor를 수용할 수 있게하는 Element 인터페이스와 Visitor 인터페이스입니다.// Element 인터페이스 public interface AttendanceElement { Detail accept(Visitor visitor); } // Visitor 인터페이스 public interface Visitor { Detail visitWorkRecord(WorkRecord workRecord); Detail visitLeaveRecord(LeaveRecord leaveRecord); }Element인터페이스는 Visitor를 수용할 수 있게하는 accept 메소드만을 구현하고, 그렇게 각 객체에서 받아들여진 Visitor는 객체의 상태에 맞게 원하는 메소드를 실행하게 하면 됩니다.public abstract class AttendanceStatus implements AttendanceElement { @Override abstract public Detail accept(Visitor visitor); } public class LeaveRecord extends AttendanceStatus { @Override public Detail accept(Visitor visitor) { return visitor.visitLeaveRecord(this); } } public class WorkRecord extends AttendanceStatus { @Override public Detail accept(Visitor visitor) { return visitor.visitWorkRecord(this); } }이렇게 Element인터페이스를 상속받은 각 객체들은 accept를 구현하게 되고, Visitor를 수용해 자신의 상태에 맞는 메소드를 실행할 수 있게 되었습니다.public class AttendanceVisitor implements Visitor{ @Override public Detail visitWorkRecord(WorkRecord workRecord) { return new Detail( workRecord.getAttendanceDate(), workRecord.getWorkingMinute(), false); } @Override public Detail visitLeaveRecord(LeaveRecord leaveRecord) { return new Detail( leaveRecord.getAttendanceDate(), 0L, true); } }Service 단에서 로직을 처리할 수 있는 Visitor를 전달함으로써 손쉽게 기존 설계를 해치지 않고 로직을 처리할 수 있게 되었습니다!이번 프로젝트를 해결하며 새로운 디자인 패턴을 공부하고 적용해볼 수 있어 좋은 기회였다 생각합니다!