Java访问者设计模式详细讲解
什么是访问者设计模式?
访问者设计模式是一种行为型设计模式,它允许你将对象元素操作与其所在的对象分离开来,并将其封装在另一个对象中。通过这种方式,我们可以在不改变被访问对象的类的前提下,增加新的功能操作。访问者模式在实际应用中非常常见,例如在编译器中,AST(抽象语法树)节点经常会被访问者模式处理。
访问者设计模式的结构
- Visitor(访问者):定义具体的访问行为,也称为操作类。
- ConcreteVisitor(具体访问者):访问者实现类。
- Element(元素):定义一个接受访问者的接口。
- ConcreteElement(具体元素):元素实现类,实现接口定义的接收行为。
- ObjectStructure(对象结构):可以是一个组合或集合,包含元素对象。
访问者模式的实现
我们现在来看一个简单的示例进行说明。假设我们有一个简单的电视机程序,电视机包含多个部分,包括电视机、桌面、音响等等。现在,我们想要访问每个部分并进行一些操作,这时我们可以使用访问者模式。
定义角色
我们来看一下这个示例中访问者设计模式的角色定义。
// 定义元素接口
public interface TvPart {
public void accept(TvPartVisitor visitor);
}
// 定义元素实现
public class Tv implements TvPart {
TvPart[] parts;
public Tv(){
parts = new TvPart[] {new Desktop(), new Speaker()};
}
public void accept(TvPartVisitor visitor) {
for (int i = 0; i < parts.length; i++) {
parts[i].accept(visitor);
}
visitor.visit(this);
}
}
public class Desktop implements TvPart {
public void accept(TvPartVisitor visitor) {
visitor.visit(this);
}
}
public class Speaker implements TvPart {
public void accept(TvPartVisitor visitor) {
visitor.visit(this);
}
}
// 定义访问者接口
public interface TvPartVisitor {
public void visit(Tv tv);
public void visit(Desktop desktop);
public void visit(Speaker speaker);
}
// 定义访问者实现类
public class TvVisitor implements TvPartVisitor {
public void visit(Tv tv) {
System.out.println("Visiting TV.");
}
public void visit(Desktop desktop) {
System.out.println("Visiting Desktop.");
}
public void visit(Speaker speaker) {
System.out.println("Visiting Speaker.");
}
}
调用示例
我们现在来看一下,如何调用这个访问者设计模式的实现。
public class VisitorTest {
public static void main(String[] args) {
TvPart tv = new Tv();
tv.accept(new TvVisitor());
}
}
示例说明
在上述示例中,我们定义了访问者接口TvPartVisitor
和元素接口TvPart
。其中,元素接口中定义了一个参数为Visitor类型的接受访问者的方法。我们还要定义元素的实现类Tv
、Desktop
和Speaker
,它们也实现了TvPart
接口,同时它们也接受了Visitor的访问。另外,我们还定义了访问者的实现类TvVisitor
,该访问者实现了TvPartVisitor
接口,并且针对不同的元素类提供了不同的访问操作。最后,我们在VisitorTest
类中调用了TvVisitor
来访问Tv
元素。
示例2:一个完整的访问者设计模式的例子
我们来看一个更加完整的示例。假设我们有一个游戏,里面包含了多个游戏区域。现在,我们想要针对不同的游戏区域,进行不同的操作,比如打印区域信息、计算区域有效面积等等。这个时候,我们可以使用访问者设计模式。
定义角色
// Element:定义一个访问者接受方法
public interface GameZone {
void accept(GameZoneVisitor visitor);
}
// Element ElementA:实现访问者接受方法
public class WoodZone implements GameZone {
private double width;
private double length;
public WoodZone(double width, double length) {
this.width = width;
this.length = length;
}
public void accept(GameZoneVisitor visitor) {
visitor.visitWoodZone(this);
}
public double getWidth() {
return width;
}
public double getLength() {
return length;
}
}
// Element ElementB:实现访问者接受方法
public class WaterZone implements GameZone {
private double radius;
public WaterZone(double radius) {
this.radius = radius;
}
public void accept(GameZoneVisitor visitor) {
visitor.visitWaterZone(this);
}
public double getRadius() {
return radius;
}
}
// Visitor:定义多个访问者方法
public interface GameZoneVisitor {
void visitWoodZone(WoodZone woodZone);
void visitWaterZone(WaterZone waterZone);
}
// Visitor VisitorA:实现多个访问者方法
public class PrintGameZoneVisitor implements GameZoneVisitor {
public void visitWoodZone(WoodZone woodZone) {
System.out.println("这是一个长方形小区域,长宽分别为: " + woodZone.getLength() + " "
+ woodZone.getWidth());
}
public void visitWaterZone(WaterZone waterZone) {
System.out.println("这是一个圆形水域,半径为:" + waterZone.getRadius());
}
}
// Visitor VisitorB:实现多个访问者方法
public class CalculateAreaVisitor implements GameZoneVisitor {
double totalArea = 0;
public void visitWoodZone(WoodZone woodZone) {
totalArea += woodZone.getWidth() * woodZone.getLength();
}
public void visitWaterZone(WaterZone waterZone) {
totalArea += Math.PI * Math.pow(waterZone.getRadius(), 2);
}
public double getTotalArea() {
return totalArea;
}
}
调用示例
我们现在来看一下,如何调用这个访问者设计模式的实现。
public class GameZoneTest {
public static void main(String[] args) {
GameZone[] zones = { new WoodZone(3, 2), new WaterZone(1.5) };
PrintGameZoneVisitor printVisitor = new PrintGameZoneVisitor();
CalculateAreaVisitor areaVisitor = new CalculateAreaVisitor();
for (GameZone zone : zones) {
zone.accept(printVisitor);
zone.accept(areaVisitor);
}
System.out.println("所有区域的有效面积:" + areaVisitor.getTotalArea());
}
}
示例说明
在上述示例中,我们定义了元素接口GameZone
,同时我们定义了两个元素类WoodZone
和WaterZone
,它们都实现了GameZone
接口,并且在实现类中都实现了接受访问方法accept
,用以接收不同的访问者操作。我们还定义了访问者接口GameZoneVisitor
,并且我们在实现了访问者接口的PrintGameZoneVisitor
和CalculateAreaVisitor
中,都实现了不同的访问操作。最后,在GameZoneTest
类中,我们调用了这些访问者,并执行了相应的操作。
总的来说,访问者设计模式可以使得算法的不同实现与对象的结构分离开来,这样,算法就可以被独立的改变和重复利用了。虽然这个模式会增加代码的复杂度,但是,如果可能存在多种实现方式的情况下,访问者的模式会更为合适。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java访问者设计模式详细讲解 - Python技术站