비지터(방문자) 패턴
객체 그룹(콜렉션)에 대해 연산을 추가할 때, 연산을 그들이 작동하는 객체로부터 분리하는 패턴.
수행해야 하는 연산을 클래스에 정의하는 대신, 비지터라는 별도 클래스에 배치한다.
사용 시점 및 이유
- 객체 그룹(콜렉션)을 순회하면서 연산을 수행해야 할 때
- 그 연산이 메인이 아닌 보조연산으로 판단되어 클래스에서 떼어내고 싶을 때
- 혹은 클래스 계층 구조에서 일부 클래스에만 그 연산이 필요할 때
- 객체 구조(상속)는 거의 변하지 않지만, 전체 구조에 걸쳐 새로운 연산이 추가될 확률이 높을 때
구현
- Element 구상 클래스에 따라 다른 구현 로직이 수행되어야 한다.
- 연산 클래스(visitor) 에서 한개의 메소드에서 instanceOf로 분기? -> visitor추가시 instanceOf 휴먼에러 발생 가능성, 코드 가독성 감소
- 그러면 오버로딩으로 구상클래스를 받도록 메소드를 선언? -> 클라이언트에서 콜렉션에 대해 반복문을 돌리는 경우 인터페이스로 엘리먼트를 받으므로 구상클래스가 어느것인지 판단할 수 없고, 오버로딩을 사용할 수 없다.
- 따라서 클라이언트가 메소드를 선택하도록 하는 것이 아닌, 각 구상 클래스 엘리먼트들 에게 선택하도록 한다.
acceptor.accept(visitor) -> visitor.visit(this)
- visitor클래스를 확장하여 서브클래싱 하는 것은 Element들에 대해 연산을 추가하는 것이다. 따라서 연산 기능 확장에 있어서 열려있다. -> 연산 추가를 위해 서브클래스들을 전부 수정할 필요가 없다.
- (단점)단 Element의 서브클래스를 추가하기는 어렵다. 연산들(visitor 서브클래스)에 새로운 Element 서브 클래스에 대한 연산들도 전부 추가해줘야 한다.
- Element캡슐화가 깨진다. visitor클래스에서 Element구상클래스의 정보에 대부분 접근 가능해야 한다.
'디자인패턴' 카테고리의 다른 글
(행동패턴) 템플릿메서드 패턴 (0) | 2023.05.10 |
---|---|
(행동패턴) 전략 패턴 (0) | 2023.05.10 |
(행동패턴) 상태 패턴 (0) | 2023.05.08 |
(행동패턴) 옵저버 패턴 (0) | 2023.05.08 |
(행동패턴) 메멘토 패턴 (0) | 2023.05.08 |