---
# System prepended metadata

title: Visitor
tags: [Design Pattern]

---

---
tags: Design Pattern
---

# Visitor

## define:

訪問者模式( Visitor )，表示一個作用於某物件結構中的各元素之操作。它使你可以再不改變各元素之類別的前提之下，定義作用於這些元素的新操作。
-- Design Pattern by GoF [大話設計模式 p.434]

Visitor mode ( Visitor ), which represents an operation that acts on each element in the structure of an object. It allows you to define new operations on elements without changing their class.
-- Design Pattern by GoF [Dahua Design Patterns p.434]

<font color="#f00">advantage:</font>

1. Separate processing from data


<font color="#f00">disadvantage:</font>

1. Arbitrary use will lead to difficulties in data expansion

---

## time to use

在資料個數是固定的時候使用；可以在不影響的情況下擴充功能，每增加一個功能就會增加一個新的Visitor；但如果過度的使用的話會導致之後的維護困難。


It is used when the number of data is fixed; the function can be expanded without affecting it, and a new Visitor will be added for each additional function; but if it is used excessively, it will cause difficulty in subsequent maintenance.

---

shape_visitor.h

定義visitor的範疇，這邊是把功能區分給圓形使用、給方形使用、給三角形使用以及給不規則形狀使用等等。

Define the category of visitor, here is to distinguish functions for circles, squares, triangles, and irregular shapes, etc.

```cpp=
#pragma once

class Circle;
class Rectangle;
class Triangle;
class CompoundShape;

class ShapeVisitor
{
public:
    virtual ~ShapeVisitor(){};

    virtual void visitCircle(Circle *circle) = 0;
    virtual void visitRectangle(Rectangle *rectangle) = 0;
    virtual void visitTriangle(Triangle *triangle) = 0;
    virtual void visitCompoundShape(CompoundShape *compoundShape) = 0;

protected:
    ShapeVisitor(){};
};
```
---

shape_info_visitor.h

繼承至shape_visitor.h，他的職責是擴充元件的詳細資料查詢功能。


Inherited to shape_visitor.h, his responsibility is to expand the detailed information query function of components.

```cpp=
#pragma once

#include <string>
#include <sstream>

#include "./shape_visitor.h"
#include "../circle.h"
#include "../compound_shape.h"
#include "../rectangle.h"
#include "../triangle.h"

class ShapeInfoVisitor : public ShapeVisitor
{
public:
    ShapeInfoVisitor() {}
    void visitCircle(Circle *circle)
    {
        for (int i = 0; i < depth; i++)
        {
            result += "  ";
        }
        result = result + circle->info() + "\n";
    }
    void visitRectangle(Rectangle *rectangle)
    {
        for (int i = 0; i < depth; i++)
        {
            result += "  ";
        }
        result = result + rectangle->info() + "\n";
    }
    void visitTriangle(Triangle *triangle)
    {
        for (int i = 0; i < depth; i++)
        {
            result += "  ";
        }
        result = result + triangle->info() + "\n";
    }
    void visitCompoundShape(CompoundShape *compoundShape)
    {
        for (int i = 0; i < depth; i++)
        {
            result += "  ";
        }
        result += "CompoundShape{\n";
        depth++;
        Iterator *it = compoundShape->createIterator();
        for (it->first(); !it->isDone(); it->next())
        {
            it->currentItem()->accept(this);
        }
        depth--;
        for (int i = 0; i < depth; i++)
        {
            result += "  ";
        }
        depth--;
        result += "}\n";
    }
    std::string getResult() { return result; };

private:
    int depth = 0;
    std::string result = "";
};
```

---

test

```cpp=
TEST(CaseShapeInfoVisitor, VisitTriangle)
{
    TwoDimensionalVector vec1(3.0, 4.0);
    TwoDimensionalVector vec2(3.0, 0.0);
    Shape *t = new Triangle(vec1, vec2);
    ShapeInfoVisitor visitor;
    t->accept(&visitor);
    std::string result = visitor.getResult();
    ASSERT_EQ("Triangle ([3.00,4.00] [3.00,0.00])\n", result);
    delete t;
}
```


The relevant code is in: https://github.com/andy091045/Design-Pattern/tree/main/posd2021f_hw4/posd2021f_110598066_hw

reference: https://ithelp.ithome.com.tw/articles/10208766