设计模式(21/23) - 访问者模式

121 阅读3分钟

访问者模式

1 概述

  • 访问者模式(Visitor Pattern)是一种行为型设计模式,它允许你在不修改对象结构的前提下定义作用于这些对象的新操作。访问者模式通过将数据结构和操作分离,使得操作可以在不改变数据结构的情况下变化。
  • 访问者模式通过引入访问者对象,将对数据结构的操作封装到访问者中,从而实现操作的灵活扩展。

2 优缺点及应用场景

2.1 优点

  • 1)扩展性强:可以在不修改数据结构的前提下,通过增加新的访问者来增加新的操作。
  • 2)符合单一职责原则:可以将不同的操作封装到不同的访问者中,使得每个访问者只负责一种操作。
  • 3)简化数据结构类:数据结构类不需要包含所有操作的代码,简化了类的定义。

2.2 缺点

  • 1)增加系统复杂性:需要定义大量的访问者类和数据结构类,增加了系统的复杂性。
  • 2)违反开闭原则:每次增加新的数据结构时,都需要修改所有访问者类,违反了开闭原则。

2.3 应用场景

  • 1)对象结构相对稳定:数据结构相对稳定,但操作经常变化的场景。
  • 2)需要对一个对象结构中的对象进行很多不同的操作:可以通过访问者模式,将操作封装到不同的访问者中。
  • 3)跨越多个类的复杂操作:需要对多个类的对象进行复杂操作时,可以使用访问者模式。

3 结构

  • 1)访问者(Visitor):定义访问数据结构中元素的接口,为每个具体元素类提供一个访问操作。
  • 2)具体访问者(ConcreteVisitor):实现访问者接口,为每个具体元素类实现访问操作。
  • 3)元素(Element): 定义接受访问者的方法,通常通过一个接口或抽象类来定义。
  • 4)具体元素(ConcreteElement):实现元素接口,实现接受访问者的方法。
  • 5)对象结构(ObjectStructure):维护一组元素对象,可以遍历这些元素并执行访问者的操作。

4 实现

4.1 UML 类图

访问者模式.jpg

4.2 代码示例

// 定义一个表示元素的接口
interface ComputerPart {
  public void accept(ComputerPartVisitor computerPartVisitor);
}

// 创建扩展了上述类的实体类:键盘
class Keyboard implements ComputerPart {
  @Override
  public void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

// 创建扩展了上述类的实体类:监视器
class Monitor implements ComputerPart {

  @Override
  public void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

// 创建扩展了上述类的实体类:鼠标
class Mouse implements ComputerPart {
  @Override
  public void accept(ComputerPartVisitor computerPartVisitor) {
    computerPartVisitor.visit(this);
  }
}

// 创建扩展了上述类的实体类:电脑
class Computer implements ComputerPart {
  ComputerPart[] parts;

  public Computer() {
    parts = new ComputerPart[]{new Mouse(), new Keyboard(), new Monitor()};
  }

  @Override
  public void accept(ComputerPartVisitor computerPartVisitor) {
    for (int i = 0; i < parts.length; i++) {
      parts[i].accept(computerPartVisitor);
    }
    computerPartVisitor.visit(this);
  }
}

// 定义一个表示访问者的接口
interface ComputerPartVisitor {
  public void visit(Computer computer);

  public void visit(Mouse mouse);

  public void visit(Keyboard keyboard);

  public void visit(Monitor monitor);
}

// 创建实现了上述类的实体访问者
class ComputerPartDisplayVisitor implements ComputerPartVisitor {
  @Override
  public void visit(Computer computer) {
    System.out.println("Displaying Computer.");
  }

  @Override
  public void visit(Mouse mouse) {
    System.out.println("Displaying Mouse.");
  }

  @Override
  public void visit(Keyboard keyboard) {
    System.out.println("Displaying Keyboard.");
  }

  @Override
  public void visit(Monitor monitor) {
    System.out.println("Displaying Monitor.");
  }
}

// 使用示例
public class VisitorPatternDemo {
  public static void main(String[] args) {
    // 使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分
    ComputerPart computer = new Computer();
    computer.accept(new ComputerPartDisplayVisitor());
  }
}
  • 执行程序,输出结果:
Displaying Mouse.
Displaying Keyboard.
Displaying Monitor.
Displaying Computer.

5 总结

  • 访问者模式通过将操作封装到访问者中,实现了操作的灵活扩展和数据结构的解耦。访问者模式适用于对象结构相对稳定、需要对一个对象结构中的对象进行很多不同的操作以及需要跨越多个类的复杂操作的场景。尽管访问者模式增加了系统的复杂性,但它在实现操作扩展和保持数据结构稳定方面具有显著优势。在实际应用中,需要根据具体需求合理使用访问者模式,以实现灵活可扩展的系统设计。