---
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