访问者模式(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)); } } }