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
circleandrectanglehascalculatePermiteter()method - I want to add
calculateArea()without chaningcircleandrectangle
β Diagram
ππ» before
circleandrectanglehas 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 insideCirclenorRectangle- 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
circleandrectangledo NOT how tocalculateParameter()β- 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
circlecode
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
triangleclass 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.
