Post

Behavioral_Visitor

βœ… Visitor Pattern

  • add new operations to existing object structures
  • without modifying those classes
  • πŸ‘‰πŸ» separate algorithms(operations) from the objects on which they operate

  • πŸ‘€ Shapes such as circle and rectangle has calculatePermiteter() method
  • I want to add calculateArea() without chaning circle and rectangle

βœ… Diagram

Screenshot-2026-03-08-at-23-11-15.png

πŸ‘ŽπŸ» before

  • circle and rectangle has their own operations
1
2
3
4
5
6
7
class Circle{
  calculatePermiteter();
}

class Rectangle{
  calculatePermiteter();
}
  • πŸ‘ŽπŸ» If I want to add calculateArea(), I need to change the code for both classes
  • πŸ‘ŽπŸ» violate open/closed principle

πŸ‘πŸ» after

  • calculatePermiteter() is not inside Circle nor Rectangle
  • objects only accept visitors
  • and the visitors will perform the operation

βœ”οΈ Element

  • now elements only accept visitor
1
2
3
interface Shape {
    void accept(Visitor visitor);
}

βœ”οΈ Concrete Element

  • circle and rectangle do NOT how to calculateParameter() ❌
  • only knows how to accept visitor
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Circle implements Shape {

    double radius;

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

class Rectangle implements Shape {
    double width, height;

    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

βœ”οΈ Visitor

1
2
3
4
5
// Visitor interface
interface Visitor {
    void visit(Circle circle);
    void visit(Rectangle rectangle);
}

βœ”οΈ Concrete visitor

  • visitor will do all the work of calculateParameter()
  • as PerimeterVisitor
1
2
3
4
5
6
7
8
9
10
11
class PerimeterVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {
        //define how to get perimeter for circle
    }

    @Override
    public void visit(Rectangle rectangle) {
        //define how to get perimeter for rectangle
    }
}

πŸ’‘ Add more functions

  • now if I want to add operation calculateArea()
  • I can just create a new visitor
  • πŸ‘πŸ» do not have to change circle code
1
2
3
4
5
6
7
8
9
10
11
class AreaVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {
        //calculate circle area
    }

    @Override
    public void visit(Rectangle rectangle) {
        //calculate rectangle area
    }
}

πŸ’‘ Add more shapes

  • now if I want to add Element like triangle,
  • create triangle class and make it accept() visitor
  • and create visitor for triangle
1
2
3
4
5
6
class Triangle implements Shape {
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
1
2
3
4
5
6
7
8
9
10
class PerimeterVisitor implements Visitor {
    @Override
    public void visit(Circle circle) {}
    @Override
    public void visit(Rectangle rectangle) {}
    @Override
    public void visit(Triangle triangle) {
      //define how to calculate perimeter for triangle
    }
}

βœ”οΈ Client

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Main {
    public static void main(String[] args) {
        Shape circle = new Circle(5);
        Shape rectangle = new Rectangle(4, 6);

        Visitor areaVisitor = new AreaVisitor();
        Visitor perimeterVisitor = new PerimeterVisitor();

        circle.accept(areaVisitor); //calculate circle area
        rectangle.accept(areaVisitor);

        circle.accept(perimeterVisitor); //calculate circle perimeter
        rectangle.accept(perimeterVisitor);
    }
}

πŸ› οΈ

  • class structure은 stableν•˜κ²Œ μž‘ν˜”λŠ”λ°
  • 계속 μƒˆλ‘œμš΄ operation을 μΆ”κ°€ν•˜κ³  싢을 λ•Œ
  • used for file system
  • for calculating file size, compression
This post is licensed under CC BY 4.0 by the author.