访问者模式(Visitor)是一种行为型设计模式,它允许你将算法与对象结构分离开来,使得算法可以独立于对象结构而变化。
在访问者模式中,有两个主要的角色:访问者(Visitor)和被访问者(Element)。访问者定义了一组访问方法,每个方法对应一个被访问者的类。被访问者定义了一个 accept 方法,该方法接受一个访问者作为参数,并调用访问者的相应方法。
下面是一个简单的访问者模式的示例代码:
// 访问者接口
interface Visitor {
void visit(ElementA element);
void visit(ElementB element);
}具体访问者实现
class ConcreteVisitor implements Visitor {
@Override
public void visit(ElementA element)
{
System.out.println(“访问者访问元素A”);
}
}被访问者接口
interface Element {
void accept(Visitor visitor);
}具体被访问者实现
class ElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visit(this);
}
}
class ElementB implements Element {
@Override public void accept(Visitor visitor) {
visitor.visit(this);
}
}客户端代码
public class Client {
public static void main(String[] args) {
Visitor visitor = new ConcreteVisitor();
Element elementA = new ElementA();
Element elementB = new ElementB();
elementA.accept(visitor);
elementB.accept(visitor);
}
}输出结果为:
访问者访问元素A 访问者访问元素B
在上面的示例中,访问者接口定义了两个访问方法,分别对应被访问者 ElementA 和 ElementB。
具体访问者实现 ConcreteVisitor 实现了这两个方法。
被访问者接口 Element 定义了一个 accept 方法,该方法接受一个访问者作为参数,并调用访问者的相应方法。
具体被访问者实现 ElementA 和 ElementB 分别实现了 accept 方法,并将自身作为参数传递给访问者。
客户端代码创建了一个具体访问者实例和两个具体被访问者实例,并调用它们的 accept 方法,将访问者作为参数传递进去。
最终,访问者会访问被访问者,并执行相应的操作。
下面是一个更详细的例子,以计算矩形和圆形的周长和面积为例
Rectangle.java
public class Rectangle implements IShape {
@Override
public double calculate(ICalculator calculator) {
return calculator.calculate(this);
}
private double width;
private double height;
public double getWidth() {
return width;
}
public void setWidth(double width) {
this.width = width;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
}IShape.java
public interface IShape {
double calculate(ICalculator calculator);
}ICalculator.java
public interface ICalculator {
double calculate(Rectangle shape);
double calculate(Circle shape);
}Area.java
public class Area implements ICalculator {
@Override
public double calculate(Rectangle shape) {
return shape.getWidth() * shape.getHeight();
}
@Override
public double calculate(Circle shape) {
return 3.14 * shape.getRadius() * shape.getRadius();
}
}VisitorClient.java
public class VisitorClient {
public static void main(String[] args) {
List < IShape > list = new ArrayList < > ();
list.add(new Rectangle(1, 2));
list.add(new Circle(3));
Area area = new Area();
Perimeter perimeter = new Perimeter();
for (IShape shape: list) {
System.out.println(shape.getClass().getSimpleName() + "面积:" + shape.calculate(area) + ",周长:" + shape.calculate(perimeter));
}
}
}