介绍
访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不改变对象结构的前提下,定义作用于这些对象的新操作。这种模式通过将操作逻辑从对象结构中抽离出来,使得新的操作可以无缝地添加到现有对象中。
1.定义
访问者模式定义了一个访问者接口,它包含了访问不同元素的操作方法。具体的元素类接受访问者并调用相应的访问方法。通过这种分离,新增的操作可以直接通过访问者来实现,而不需要修改元素类。
2. 主要作用
- 允许在不修改元素类的情况下,定义新的操作。
- 提高了系统的可扩展性。
- 避免了对复杂对象结构的直接修改。
3. 解决的问题
访问者模式解决了如何在不修改对象结构的情况下,向对象添加新的操作的问题。尤其在系统需要频繁添加新操作时,显得尤为重要。
4. 模式原理
包含角色:
- Visitor:定义了对各类元素对象的操作接口。
- ConcreteVisitor:实现Visitor接口,具体实现访问操作。
- Element:定义接受访问者的方法accept(), 通常由具体元素实现。
- ConcreteElement:实现Element接口,实现accept()方法。
- ObjectStructure:维护Element对象的集合,并提供遍历功能。
看到这么多的角色,就知道访问者模式并不简单,毕竟它是 《设计模式》中较为复杂的一个。不用怕,先以了解为主,因为它在实际开发中毕竟不常用。
UML类图:
示例: 假设我们有一个表示不同形状(如圆形和矩形)的对象结构,我们希望对这些形状执行不同的操作(如计算面积和绘制形状)。
定义形状接口和具体形状类:
// Shape接口
interface Shape {
void accept(Visitor visitor);
}
// 圆形类
class Circle implements Shape {
double radius;
Circle(double radius) {
this.radius = radius;
}
public double getRadius() {
return radius;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
// 矩形类
class Rectangle implements Shape {
double width;
double height;
Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
public double getWidth() {
return width;
}
public double getHeight() {
return height;
}
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
定义访问者接口和具体访问者类:
// 访问者接口
interface Visitor {
void visit(Circle circle);
void visit(Rectangle rectangle);
}
// 具体访问者类 - 计算面积
class AreaVisitor implements Visitor {
@Override
public void visit(Circle circle) {
double area = Math.PI * circle.getRadius() * circle.getRadius();
System.out.println("Circle area: " + area);
}
@Override
public void visit(Rectangle rectangle) {
double area = rectangle.getWidth() * rectangle.getHeight();
System.out.println("Rectangle area: " + area);
}
}
// 具体访问者类 - 绘制形状
class DrawVisitor implements Visitor {
@Override
public void visit(Circle circle) {
System.out.println("Drawing a Circle with radius " + circle.getRadius());
}
@Override
public void visit(Rectangle rectangle) {
System.out.println("Drawing a Rectangle with width " + rectangle.getWidth() + " and height " + rectangle.getHeight());
}
}
使用访问者模式:
public class VisitorPatternDemo {
public static void main(String[] args) {
Shape circle = new Circle(5);
Shape rectangle = new Rectangle(4, 6);
Visitor areaVisitor = new AreaVisitor();
Visitor drawVisitor = new DrawVisitor();
System.out.println("Calculating areas:");
circle.accept(areaVisitor);
rectangle.accept(areaVisitor);
System.out.println("\nDrawing shapes:");
circle.accept(drawVisitor);
rectangle.accept(drawVisitor);
}
}
打印输出:
Calculating areas:
Circle area: 78.53981633974483
Rectangle area: 24.0
Drawing shapes:
Drawing a Circle with radius 5.0
Drawing a Rectangle with width 4.0 and height 6.0
说真的,写到这里我还是懵懵的,但隐约感觉这个设计不错,哈哈哈。
举个栗子,假如你是个想了解学生信息的老师(Visitor
),你可以是班主任也可以是体育老师(ConcreteVisitor
),因为他们的关注点不同(例如,班主任关注学生的学习成绩,体育老师关注学生的运动能力),学校里的不同类型的学生(Element
),具体的学生(ConcreteElement
)(例如文艺生A,运动生B)。
此时,假设我们有一个学校系统,其中有多种学生类型和评价标准。
- 学生接口(Student):定义一个
accept(Visitor visitor)
方法。 - 具体学生(SpecificStudent):实现
Student
接口,能够接受不同的访问者。 - 访问者接口(Visitor):定义访问不同学生类型的方法,如
visit(ArtStudent artStudent)
和visit(SportsStudent sportsStudent)
。 - 具体访问者(ConcreteVisitor):实现具体的访问逻辑,比如
AcademicEvaluator
关注学术成绩,PhysicalEducationEvaluator
关注体育表现。
回头再看一遍定义,访问者模式定义了一个访问者接口,它包含了访问不同元素的操作方法,此处的不同元素就是不同的学生,具体的元素类接受访问者并调用相应的访问方法,此处的相应的访问方法就是 学术成绩 和 体育表现,通过这种方式,可以在不改变学生对象结构的前提下,增加新的评价逻辑或操作,而不需要修改学生类本身。
到这里,是不是更进一步了解访问者模式了,不明白也不要紧,记住定义就行了。我突然想到我高中数学老师说的一句话:别管为啥这样写,你就记住,这样写就给分!哈哈。有时候不必太纠结,现在不明白 后面你也会明白的
标签:double,void,成神,Visitor,设计模式,public,rectangle,访问者 From: https://blog.51cto.com/xaye/11984189