Luckylau's Blog

设计模式之访问者模式

​ 在访问者模式(Visitor Pattern)中,通过一个访问者类,来封装对数据结构中不同类型元素的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。这种类型的设计模式属于行为型模式。

​ 我们假设有一些形状,包括三角形、矩形和圆形这三种不同的几何形状。我们知道不同的形状其参数是不同的:三角形:三条边的长度确定一个三角形;矩形:长和宽确定一个矩形;圆形就一个参数——半径。
那么任务来了,我们把一系列类型和参数不同的形状用ArrayList来管理,然后依次遍历,并计算出它们的周长。

1
2
3
4
5
public interface Calculator {
double ofShape(Triangle triangle);
double ofShape(Circle circle);
double ofShape(Square square);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
public class Perimeter implements Calculator {
public double ofShape(Triangle triangle) {
return triangle.getEdgeA() + triangle.getEdgeB() + triangle.getEdgeC();
}
public double ofShape(Circle circle) {
return circle.getRadius() * Math.PI * 2;
}
public double ofShape(Square square) {
return square.getEdge() * 4;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Area implements Calculator {
public double ofShape(Triangle triangle) {
double a = triangle.getEdgeA(), b = triangle.getEdgeB(), c = triangle.getEdgeC();
double p = (a + b + c) / 2;
return Math.sqrt(p * (p - a) * (p - b) * (p - c));
}
public double ofShape(Circle circle) {
return Math.PI * circle.getRadius() * circle.getRadius();
}
public double ofShape(Square square) {
return Math.pow(square.getEdge(), 2);
}
}
1
2
3
4
public interface Shape {
// 对于不同的计算策略来者不拒
double accept(Calculator calculator);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
public class Triangle implements Shape {
private double edgeA;
private double edgeB;
private double edgeC;
public Triangle(double edgeA, double edgeB, double edgeC) {
this.edgeA = edgeA;
this.edgeB = edgeB;
this.edgeC = edgeC;
}
public double getEdgeA() {
return edgeA;
}
public double getEdgeB() {
return edgeB;
}
public double getEdgeC() {
return edgeC;
}
// 方法接受策略对象为参数,方法内将自身作为参数再传给策略的方法
public double accept(Calculator calculator) {
return calculator.ofShape(this);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class Circle implements Shape {
private double radius;
public Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
public double accept(Calculator calculator) {
return calculator.ofShape(this);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Client {
public static void main(String[] args) {
// 一个含有5个元素的List,包含三种不同的形状
List<Shape> shapes = new ArrayList<Shape>();
shapes.add(new Triangle(1.3, 2.2, 3.1));
shapes.add(new Circle(1.2));
shapes.add(new Triangle(2.4, 3.3, 4.2));
shapes.add(new Rectangle(2.1, 3.2));
shapes.add(new Circle(5.6));
// 计算周长和面积的不同策略(访问者)
Perimeter perimeter = new Perimeter();
Area area = new Area();
// 将周长和面积的计算策略传入(接受不同访问者的访问)
for (Shape shape : shapes) {
System.out.printf("周长 : %5.2f\t 面积 : %5.2f\n", shape.accept(perimeter), shape.accept(area));
}
}
}
Luckylau wechat
如果对您有价值,看官可以打赏的!