Visitor Pattern(๋น„์ง€ํ„ฐ ํŒจํ„ด)

๊ฐ์ฒด(๋ฐ์ดํ„ฐ ๊ตฌ์กฐ)์™€ ๋กœ์ง(์•Œ๊ณ ๋ฆฌ์ฆ˜)์„ ๋ถ„๋ฆฌํ•˜๋Š” ๋””์ž์ธ ํŒจํ„ด
์ƒˆ๋กœ์šด ๋กœ์ง์„ ์ถ”๊ฐ€ํ•˜๋”๋ผ๋„ ๊ฐ์ฒด์˜ ๊ตฌ์กฐ๋Š” ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์€ ์ฑ„ ์ƒˆ๋กœ์šด ๋™์ž‘์„ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

Visitor Pattern์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๋นŒ๋“œ ์—…

์œ ๋ฆฌ์ปต๊ณผ ์‹ ์„  ์‹ํ’ˆ์„ ํŒŒ๋Š” ์‡ผํ•‘๋ชฐ ์‚ฌ์žฅ๋‹˜์ด ๋๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ๋ˆˆ์น˜ ์ฑ˜๊ฒ ์ง€๋งŒ ์ด ์˜ˆ์ œ์—์„œ ๊ฐ์ฒด๋Š” ์ƒํ’ˆ(์œ ๋ฆฌ์ปต, ์‹ ์„  ์‹ํ’ˆ)์ด ๋  ๊ฒƒ์ด๊ณ , ๋กœ์ง์€ ์ƒํ’ˆ ์ฃผ๋ฌธ์ด ๋  ๊ฒƒ์ด๋‹ค.

  • ์ƒํ’ˆ : ์œ ๋ฆฌ์ปต, ์‹ ์„  ์‹ํ’ˆ
  • ์ฃผ๋ฌธ : ํฌ์žฅ, ๋ฐฐ์†ก, ํฌ์ธํŠธ ์ ๋ฆฝ(์ถ”๊ฐ€ ๊ธฐ๋Šฅ)

์ด์ œ ์ด ์˜ˆ์ œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ณผ์ •์—์„œ ๋ช‡ ๊ฐ€์ง€ ๋ฌธ์ œ๋ฅผ ์งš์–ด๋ณด๊ณ , ์ด ๋ฌธ์ œ๋“ค์„ ์–ด๋–ป๊ฒŒ Visitor ํŒจํ„ด์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š”์ง€ ์•Œ์•„๋ณด์ž.


๋ฌธ์ œ 1. ์œ ์ง€ ๋ณด์ˆ˜์˜ ์–ด๋ ค์›€

  1. ์‡ผํ•‘๋ชฐ์—์„œ ํŒ๋งคํ•˜๋Š” ์ƒํ’ˆ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•˜๊ณ  ์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ์œ ๋ฆฌ์ปต๊ณผ ์‹ ์„  ์‹ํ’ˆ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
/* ์ƒํ’ˆ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Product() {
    public void pack();
    public void deliver();
}

/* ์œ ๋ฆฌ์ปต ๊ตฌํ˜„์ฒด */
public class Glass implements Product {
    // ํฌ์žฅ
    @Override
    public void pack() { System.out.println("๋ฝ๋ฝ์ด๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํฌ์žฅ"); }
    // ๋ฐฐ์†ก
    @Override
    public void deliver() {System.out.println("ํ•œ ๋‹ฌ ๋™์•ˆ ๋Š๊ธ‹ํ•˜๊ฒŒ ๋ฐฐ์†ก"); }
}
/* ์‹ ์„  ์‹ํ’ˆ ๊ตฌํ˜„์ฒด */
public class FreshGrocery implements Product {
    // ํฌ์žฅ
    @Override
    public void pack() { System.out.println("์•„์ด์ŠคํŒฉ์œผ๋กœ ์‹ ์„ ํ•˜๊ฒŒ ํฌ์žฅ"); }
    // ๋ฐฐ์†ก
    @Override
    public void deliver() {System.out.println("ํ•˜๋ฃจ๋งŒ์— ํ€ต์œผ๋กœ ๋ฐฐ์†ก"); }
}

[์‹คํ–‰]

public static void main(String[] args) {
    Product glass = new Glass();
    Product freshGrocery = new FreshGrocery();

    glass.pack();
    glass.deliver();
    freshGrocery.pack();
    freshGrocery.deliver();
}
  • ์œ„์˜ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•  ๊ฒฝ์šฐ ๋ชจ๋“  ๊ฐ์ฒด๋งˆ๋‹ค ๋กœ์ง์„ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— 1) ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ ์–ด๋ ค์šธ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ 2) ํŠน์ • ๊ฐ์ฒด์—์„œ ๋กœ์ง ๊ตฌํ˜„์„ ๋นผ๋จน๊ธฐ๋„ ์‰ฝ๋‹ค.
  • ๋˜ํ•œ ๋ชจ๋“  ๊ฐ์ฒด์— ๋Œ€ํ•ด ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์œ„์—์„œ์ฒ˜๋Ÿผ main()์—์„œ ๋ชจ๋“  ๊ฐ์ฒด ๋ณ„ ๊ฐ ํ•จ์ˆ˜๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— 3) iterator๋ฅผ ํ†ตํ•œ ๋ฐ˜๋ณต์ ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฌธ์ œ 2. ๊ฐ์ฒด ๋ถ„๊ธฐ์˜ ์–ด๋ ค์›€ ๋ฐ ์ฝ”๋“œ ์ค‘๋ณต

1๋ฒˆ ์˜ˆ์ œ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์ฒด์™€ ๊ธฐ๋Šฅ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•ด๋ณด์ž.

  1. 1๋ฒˆ ์˜ˆ์ œ์—์„œ ์ƒํ’ˆ ๊ฐ์ฒด๋“ค์€ ์œ ์ง€ํ•˜๋˜, ๊ธฐ๋Šฅ์„ ์œ„ํ•œ ๋ฉ”์„œ๋“œ๋Š” ์ œ๊ฑฐํ•œ๋‹ค.
  2. ์ฃผ๋ฌธ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ •์˜ํ•œ ๋’ค, ์ด๋ฅผ ๊ตฌํ˜„ํ•œ ์„ธ๋ถ€ ๊ธฐ๋Šฅ ๊ตฌํ˜„์ฒด๋ฅผ ์ •์˜ํ•œ๋‹ค.

[์ƒํ’ˆ ๊ฐ์ฒด]

/* ์ƒํ’ˆ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Product() { }

/* ์œ ๋ฆฌ์ปต ๊ตฌํ˜„์ฒด */
public class Glass implements Product { }
/* ์‹ ์„  ์‹ํ’ˆ ๊ตฌํ˜„์ฒด */
public class FreshGrocery implements Product { }

[์ฃผ๋ฌธ ๊ธฐ๋Šฅ]

/* ์ฃผ๋ฌธ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Order {
    public void pack(Product product);
    public void deliver(Product product);
}

/* ์ฃผ๋ฌธ ๊ตฌํ˜„์ฒด */
public class OrderImpl implements Order {
    // ํฌ์žฅ
    @Override
    public void pack(Product product) {
        if (product instanceof Glass) {
            // ์œ ๋ฆฌ์ปต ํฌ์žฅ
            System.out.println("๋ฝ๋ฝ์ด๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํฌ์žฅ");
        } else if (product instanceof FreshGrocery) {
            // ์‹ ์„  ์‹ํ’ˆ ํฌ์žฅ
            System.out.println("์•„์ด์ŠคํŒฉ์œผ๋กœ ์‹ ์„ ํ•˜๊ฒŒ ํฌ์žฅ");
        }
    }

    // ๋ฐฐ์†ก
    @Override
    public void deliver(Product product) {
        if (product instanceof Glass) {
            // ์œ ๋ฆฌ์ปต ๋ฐฐ์†ก
            System.out.println("ํ•œ ๋‹ฌ ๋™์•ˆ ๋Š๊ธ‹ํ•˜๊ฒŒ ๋ฐฐ์†ก");
        } else if (product instanceof FreshGrocery) {
            // ์‹ ์„  ์‹ํ’ˆ ๋ฒ ์†ก
            System.out.println("ํ•˜๋ฃจ๋งŒ์— ํ€ต์œผ๋กœ ๋ฐฐ์†ก");
        }
    }
}

[์‹คํ–‰]

public static void main(String[] args) {
    Product glass = new Glass();
    Product freshGrocery = new FreshGrocery();
    Order order = new OrderImpl();

    order.pack(glass);
    order.pack(freshGrocery);
    order.deliver(glass);
    order.deliver(freshGrocery);
}
  • ์œ„ ์ฝ”๋“œ๋Š” 1๋ฒˆ์˜ ๋ฌธ์ œ์ ์ธ ๋ฐ˜๋ณต์ ์ธ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ์ง€๋งŒ ์—ฌ์ „ํžˆ ๋ฌธ์ œ๊ฐ€ ๋‚จ์•„์žˆ๋‹ค. ํŠนํžˆ if (product instanceof Glass) ๋ถ€๋ถ„์œผ๋กœ ๋ถ„๊ธฐํ•˜๋Š” ๋ถ€๋ถ„์ด ์„ฑ์— ์•ˆ์ฐฌ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๊ฐ์ฒด๋ฅผ ๋ถ„๊ธฐํ•  ๊ฒฝ์šฐ 1) ํŠน์ • ๊ฐ์ฒด์— ๋Œ€ํ•œ ๋ถ„๊ธฐ๋ฅผ ๋นผ๋จน์„ ์ˆ˜๋„ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๋น„์Šทํ•œ ๊ตฌ์กฐ๊ฐ€ ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ ์ค‘๋ณต์ด ๋ฐœ์ƒํ•œ๋‹ค.
  • ์ฆ‰, 1๋ฒˆ์˜ ๋ฌธ์ œ๋ฅผ ๊ฑฐ์˜ ํ•ด๊ฒฐํ•˜์ง€ ๋ชปํ•œ ๊ฒฉ์ด๋‹ค.

๋ฌธ์ œ 3. Single Dispatch(Dynamic Dispatch) ๋ฌธ์ œ

๐Ÿ˜ฏ Dispatch๋ž€?

  • Dispatch๋ž€ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐฉ์‹์„ ๋งํ•œ๋‹ค.
  • ์ž๋ฐ”๋Š” ๋Ÿฐํƒ€์ž„ ์‹œ์— ์–ด๋–ค ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ• ์ง€ ๊ฒฐ์ •ํ•˜๋Š”, ์ฆ‰ ๋Ÿฐํƒ€์ž„ ์‹œ์— ์ƒ์„ฑ๋˜๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๋™์ ์œผ๋กœ ํƒ€์ž… ์ฒดํฌ ํ•˜๋Š” dynamic dispatch๋งŒ์„ ์ง€์›ํ•œ๋‹ค.(single dispatch)

์˜ˆ์ œ

  1. 2๋ฒˆ ์˜ˆ์ œ์˜ ์ƒํ’ˆ ๊ฐ์ฒด์™€ ์ฃผ๋ฌธ ํด๋ž˜์Šค๋ฅผ ์œ ์ง€ํ•˜๋˜, ์ฃผ๋ฌธ ํด๋ž˜์Šค์—์„œ ๊ฐ ์ƒํ’ˆ ํƒ€์ž… ๋ณ„ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

[์ฃผ๋ฌธ ๊ธฐ๋Šฅ]

/* ์ฃผ๋ฌธ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Order {
    public void pack(Glass glass);
    public void pack(FreshGrocery freshGrocery);
    public void deliver(Glass glass);
    public void deliver(FreshGrocery freshGrocery);
}

/* ์ฃผ๋ฌธ ๊ตฌํ˜„์ฒด */
public class OrderImpl implements Order {
    // ์œ ๋ฆฌ์ปต ํฌ์žฅ
    @Override
    public void pack(Glass glass) { System.out.println("๋ฝ๋ฝ์ด๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํฌ์žฅ"); }
    // ์‹ ์„  ์‹ํ’ˆ ํฌ์žฅ
    @Override
    public void pack(FreshGrocery freshGrocery) { System.out.println("์•„์ด์ŠคํŒฉ์œผ๋กœ ์‹ ์„ ํ•˜๊ฒŒ ํฌ์žฅ"); }
    
    // ์œ ๋ฆฌ์ปต ๋ฐฐ์†ก
    @Override
    public void deliver(Glass glass) { System.out.println("ํ•œ ๋‹ฌ ๋™์•ˆ ๋Š๊ธ‹ํ•˜๊ฒŒ ๋ฐฐ์†ก"); } 
    // ์‹ ์„  ์‹ํ’ˆ ๋ฐฐ์†ก
    @Override
    public void deliver(FreshGrocery freshGrocery) { System.out.println("ํ•˜๋ฃจ๋งŒ์— ํ€ต์œผ๋กœ ๋ฐฐ์†ก"); } 
}

[์‹คํ–‰]

public static void main(String[] args) {
    Product glass = new Glass();
    Product freshGrocery = new FreshGrocery();
    Order order = new OrderImpl();

    order.pack(glass);
    order.pack(freshGrocery);
    order.deliver(glass);
    order.deliver(freshGrocery);
}
  • ์ด๋ฒˆ ์˜ˆ์ œ๋Š” 2๋ฒˆ ์˜ˆ์ œ์˜ ์‹คํ–‰ ๋ถ€๋ถ„์ธ main() ๋ถ€๋ถ„์ด ๋™์ผํ•˜๋‹ค. ์–ธ๋œป๋ณด๋ฉด ๊ฐ€๋Šฅํ•ด ๋ณด์ผ์ง€๋ผ๋„ ์ด๋ฒˆ์—๋Š” ์ปดํŒŒ์ผ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ฒŒ ๋œ๋‹ค.
  • OrderImpl ํด๋ž˜์Šค ๋‚ด๋ถ€์˜ pack() ๋ฉ”์„œ๋“œ์™€ deliver() ๋ฉ”์„œ๋“œ๋Š” ๊ฐ๊ฐ ์„œ๋กœ ๋‹ค๋ฅธ ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…(Glass, FreshGrocery)์œผ๋กœ ์ •์˜ํ•˜์—ฌ ์˜ค๋ฒ„๋กœ๋”ฉํ•˜๊ณ  ์žˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์‹คํ–‰ ๋ถ€๋ถ„์—์„œ๋Š” glass์™€ freshGrocery ์ธ์Šคํ„ด์Šค ๋ชจ๋‘ Product ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‹ค์ œ๋กœ๋Š” Glass ํƒ€์ž…๊ณผ FreshGrocery ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค์ผ์ง€๋ผ๋„, Dynamic Dispatch ํŠน์„ฑ ์ƒ ์ปดํŒŒ์ผ ์‹œ Glass ํƒ€์ž…๊ณผ FreshGrocery ํƒ€์ž…์œผ๋กœ ์ธ์‹๋  ์ˆ˜ ์—†๋‹ค.
  • ๋” ์ž‘์€ ํƒ€์ž…์— ๋” ํฐ ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋„ฃ์„ ์ˆ˜ ์—†๋‹ค!!
  • ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์ž๊ณ  glass์™€ freshGrocery ์ธ์Šคํ„ด์Šค๋ฅผ Product ํƒ€์ž…์ด ์•„๋‹Œ Glass ํƒ€์ž…๊ณผ FreshGrocery ํƒ€์ž…์œผ๋กœ ์ƒ์„ฑํ•˜๊ฒŒ ๋œ๋‹ค๋ฉด ์ด๋Š” ๋” ์ด์ƒ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์˜๋ฏธ๊ฐ€ ์—†๋Š” ์ฝ”๋“œ๊ฐ€ ๋˜์–ด๋ฒ„๋ฆฐ๋‹ค.

Visitor Pattern์„ ์ด์šฉํ•œ ํ•ด๊ฒฐ ๋ฐฉ์•ˆ

์ด์ œ ์œ„์˜ ๋ฌธ์ œ์ ๋“ค์„ Visitor Pattern์„ ์ด์šฉํ•ด ํ•ด๊ฒฐํ•ด๋ณด์ž.

  1. 1๋ฒˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ์ฒด์™€ ๋กœ์ง์„ ๋ถ„๋ฆฌํ•  ๊ฒƒ์ด๋‹ค.
  2. ๋˜ํ•œ 2๋ฒˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๊ฐ ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ํ•˜๋Š” ๊ธฐ๋Šฅ ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ๊ฐ ์ •์˜ํ•œ๋‹ค.
  3. ๋งˆ์ง€๋ง‰์œผ๋กœ Double Dispatch๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ 3๋ฒˆ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•œ๋‹ค!

[์ƒํ’ˆ ๊ฐ์ฒด]

/* ์ƒํ’ˆ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Product() {
    public void order(Order order);
}

/* ์œ ๋ฆฌ์ปต ๊ตฌํ˜„์ฒด */
public class Glass implements Product {
    @Override
    public void order(Order order) {
        order.placeOrder(this);
    }
}
/* ์‹ ์„  ์‹ํ’ˆ ๊ตฌํ˜„์ฒด */
public class FreshGrocery implements Product {
    @Override
    public void order(Order order) {
        order.placeOrder(this);
    }
}

[์ฃผ๋ฌธ ๊ธฐ๋Šฅ]

/* ์ฃผ๋ฌธ ์ธํ„ฐํŽ˜์ด์Šค */
public interface Order {
    public void placeOrder(Glass glass);
    public void placeOrder(FreshGrocery freshGrocery);
}

/* ํฌ์žฅ ์ฃผ๋ฌธ ๊ตฌํ˜„์ฒด */
public class PackOrder implements Order {
    // ์œ ๋ฆฌ์ปต ํฌ์žฅ
    @Override
    public void placeOrder(Glass glass) { System.out.println("๋ฝ๋ฝ์ด๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ํฌ์žฅ"); }

    // ์‹ ์„  ์‹ํ’ˆ ํฌ์žฅ
    @Override
    public void placeOrder(FreshGrocery freshGrocery) { System.out.println("์•„์ด์ŠคํŒฉ์œผ๋กœ ์‹ ์„ ํ•˜๊ฒŒ ํฌ์žฅ"); }
}

/* ๋ฐฐ์†ก ์ฃผ๋ฌธ ๊ตฌํ˜„์ฒด */
public class DeliverOrder implements Order {
    // ์œ ๋ฆฌ์ปต ๋ฐฐ์†ก
    @Override
    public void placeOrder(Glass glass) { System.out.println("ํ•œ ๋‹ฌ ๋™์•ˆ ๋Š๊ธ‹ํ•˜๊ฒŒ ๋ฐฐ์†ก"); } 

    // ์‹ ์„  ์‹ํ’ˆ ๋ฐฐ์†ก
    @Override
    public void placeOrder(FreshGrocery freshGrocery) { System.out.println("ํ•˜๋ฃจ๋งŒ์— ํ€ต์œผ๋กœ ๋ฐฐ์†ก"); } 
}

/* ํฌ์ธํŠธ ์ ๋ฆฝ ์ฃผ๋ฌธ ๊ตฌํ˜„์ฒด */
public class pointSaveOrder implements Order {
    // ์œ ๋ฆฌ์ปต ํฌ์ธํŠธ ์ ๋ฆฝ
    @Override
    public void placeOrder(Glass glass) { System.out.println("๊ตฌ๋งค ๊ธˆ์•ก์˜ 10% ์ ๋ฆฝ"); } 

    // ์‹ ์„  ์‹ํ’ˆ ํฌ์ธํŠธ ์ ๋ฆฝ
    @Override
    public void placeOrder(FreshGrocery freshGrocery) { System.out.println("๊ตฌ๋งค ๊ธˆ์•ก์˜ 5% ์ ๋ฆฝ"); } 
}

[์‹คํ–‰]

public static void main(String[] args) {
    Product glass = new Glass();
    Product freshGrocery = new FreshGrocery();
    Order packOrder = new PackOrder();
    Order deliverOrder = new DeliverOrder();

    glass.order(packOrder);
    glass.order(deliverOrder);
    freshGrocery.order(packOrder);
    freshGrocery.order(deliverOrder);
}

Visitor ํŒจํ„ด์„ ์ ์šฉํ•œ ์ดํ›„ ๋‹ฌ๋ผ์ง„ ๋ถ€๋ถ„์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ƒํ’ˆ ๊ฐ์ฒด ๋‚ด์—์„œ ์ฃผ๋ฌธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
  • ์ฃผ๋ฌธ ๊ธฐ๋Šฅ์„ ํด๋ž˜์Šค๋กœ ๋นผ๋‚ธ ๋’ค, ๊ฐ ์ƒํ’ˆ ๊ฐ์ฒด ํƒ€์ž… ๋ณ„ ๋ณ„๋„์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„์„ ๋นผ๋จน์„ ์œ„ํ—˜์ด ์ ๋‹ค.
  • ๊ฐ ์ƒํ’ˆ ํƒ€์ž… ๊ฐ์ฒด์—์„œ ๊ธฐ๋Šฅ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— single dispatch๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜์ง€ ์•Š๋Š”๋‹ค. (๋” ํฐ ํƒ€์ž…์—์„œ ๋” ์ž‘์€ ํƒ€์ž…์˜ ๊ฐ์ฒด๋ฅผ ๋ฐ›๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—)
  • ์ƒˆ๋กœ์šด ์ฃผ๋ฌธ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•˜๊ธฐ๊ฐ€ ์‰ฝ๋‹ค! ๊ฐ์ฒด์—์„œ๋Š” ๋ณ€๊ฒฝ ์—†์ด ์˜ค์ง ์ฃผ๋ฌธ ํด๋ž˜์Šค๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

์ถ”๊ฐ€์ ์œผ๋กœ Visitor Pattern์—์„œ ํ”ํžˆ ๋งํ•˜๋Š” Visitor, Element์˜ ์—ญํ• ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋งค์นญ๋  ์ˆ˜ ์žˆ๋‹ค.

  • Visitor : ๊ธฐ๋Šฅ์ด๋‚˜ ๋กœ์ง์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค ex) Order ์ธํ„ฐํŽ˜์ด์Šค
  • ConcreteVisitor : ๊ธฐ๋Šฅ์ด๋‚˜ ๋กœ์ง ๊ตฌํ˜„์ฒด ex) PackOrder ํด๋ž˜์Šค, DeliverOrder ํด๋ž˜์Šค, pointSaveOrder ํด๋ž˜์Šค
  • visit(Element) : ๊ฐ์ฒด์—์„œ ํ˜ธ์ถœ๋˜์–ด ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋Šฅ ํด๋ž˜์Šค๊ฐ€ ๊ณตํ†ต์ ์œผ๋กœ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋ฉ”์„œ๋“œ ex) placeOrder()
  • Element : ๊ธฐ๋Šฅ์ด๋‚˜ ๋กœ์ง์„ ์‚ฌ์šฉํ•  ๊ฐ์ฒด ์ธํ„ฐํŽ˜์ด์Šค ex) Product ์ธํ„ฐํŽ˜์ด์Šค
  • ConcreteElement : ๊ฐ์ฒด ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ตฌํ˜„์ฒด ex) Glass ํด๋ž˜์Šค, FreshGrocery ํด๋ž˜์Šค
  • accept(Visitor) : ๊ธฐ๋Šฅ ํด๋ž˜์Šค ๋‚ด์˜ visit ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๊ตฌํ˜„ํ•ด์•ผ ํ•  ๋ฉ”์„œ๋“œ ex) order()


References

๋ฐฉ๋ฌธ์ž ํŒจํ„ด - Visitor pattern by Jeongjin Kim

ํ† ๋น„์˜๋ด„#01. Double Dispatch by LichKing