1. Visitor Pattern 이란?
2. Visitor Pattern의 적용 예시
1️⃣ Visitor Pattern
- 방문자와 방문 공간을 분리하여, 방문 공간이 방문자를 맞이할 때, 이후에 대한 행동을 방문자에게 위임하는 패턴
- 알고리즘을 객체 구조에서 분리시키는 디자인 패턴
⇒ 개방-폐쇄 원칙을 적용하는 방법 중 하나
⇒ 구조를 수정하지 않고도 실질적으로 새로운 동작을 기존의 객체 구조에 추가할 수 있게 된다.
예시
- 쇼핑몰 고객을 등급별로 나누고 등급에 따라 혜택을 주기로 한다.
- 등급은 Gold, Vip가 있고 혜택은 포인트, 할인이 있다.
- 고객 등급별 혜택을 줄 수 있는 확장 가능한 해결책을 찾아보자.
public interface Member { }
public class GoldMember implements Member { }
public class VipMember implements Member { }
- Member 인터페이스를 사용해서 등급별로 구체 클래스 생성
public class GoldMember implements Member {
public void point() { System.out.println("Point for Gold Member"); }
public void discount() { System.out.println("Discount for Gold Member"); }
}
public class VipMember implements Member {
public void point() { System.out.println("Point for Vip Member"); }
public void discount() { System.out.println("Discount for Vip Member"); }
}
- 등급별 혜택 구현
public class Main {
public static void main(String[] args) {
Member gold = new GoldMember();
Member vip = new VipMember();
gold.point();
vip.point();
gold.discount();
vip.discount();
}
}
//실행 결과
Point for Gold Member
Point for Vip Member
Discount for Gold Member
Discount for Vip Member
⭐ 문제점 ⭐
- 고객들에게 혜택을 주고자 할 때 명시적으로 혜택을 주기 위한 메소드를 호출해야한다.
- 혜택이 늘어났을 경우 모든 멤버들에 대해 그 혜택을 구현했다는 보장이 없다.
⭐ 해결방안 ⭐
public interface Benefit {
void getBenefit(GoldMember member);
void getBenefit(VipMember member);
}
- Benefit 인터페이스에 혜택을 받을 Member 별로 실행 가능한 메소드 정의
public class DiscountBenefit implements Benefit {
@Override
public void getBenefit(GoldMember member) {
System.out.println("Discount for Gold Member");
}
@Override
public void getBenefit(VipMember member) {
System.out.println("Discount for Vip Member");
}
}
public class PointBenefit implements Benefit {
@Override
public void getBenefit(GoldMember member) {
System.out.println("Point for Gold Member");
}
@Override
public void getBenefit(VipMember member) {
System.out.println("Point for Vip Member");
}
}
- 멤버 등급별 혜택에 대해 기능 구현
public interface Member {
void getBenefit(Benefit benefit);
}
- 등급별 멤버가 혜택을 받을 수 있는 메소드를 Member 인터페이스에 선언
public class GoldMember implements Member {
@Override
public void getBenefit(Benefit benefit) {
benefit.getBenefit(this);
}
}
public class VipMember implements Member {
@Override
public void getBenefit(Benefit benefit) {
benefit.getBenefit(this);
}
}
- 혜택받는 메소드 구현
- 다른 Member가 추가되더라도 구현 부분은 benefit.getBenefit(Benefit benefit); 만 넣으면 된다.
public class Main {
public static void main(String[] args) {
Member goldMember = new GoldMember();
Member vipMember = new VipMember();
Benefit pointBenefit = new PointBenefit();
Benefit discountBenefit = new DiscountBenefit();
goldMember.getBenefit(pointBenefit);
vipMember.getBenefit(pointBenefit);
goldMember.getBenefit(discountBenefit);
vipMember.getBenefit(discountBenefit);
}
}
//실행 결과
Point for Gold Member
Point for Vip Member
Discount for Gold Member
Discount for Vip Member
⭐ 결과 ⭐
- Visitor 패턴에서는 혜택이 늘어나더라도 Benefit 인터페이스에 명시적으로 등급별 메소드를 정의하고 있어 구현 누락이 발생하지 않는다.
- 혜택을 추가하기 위해서 해당 혜택을 구현하는 클래스를 추가하면 되므로, 코드 중복이 발생하지 않는다.
⭐ Visitor 패턴을 언제 쓰면 좋을까? ⭐
- 대상 객체가 잘 바뀌지 않고, 적용할 알고리즘이 추가될 가능성이 많은 상황일 때
참고
https://thecodinglog.github.io/design/2019/10/29/visitor-pattern.html
https://velog.io/@cham/Design-Pattern-방문자-패턴-Visitor-pattern
'정리 > Design Pattern' 카테고리의 다른 글
Flyweight Pattern - 플라이웨이트 패턴 (0) | 2022.03.31 |
---|