博客
关于我
访问者模式
阅读量:578 次
发布时间:2019-03-09

本文共 4487 字,大约阅读时间需要 14 分钟。

访问者模式(Visitor Pattern)解析

在软件设计模式中,访问者模式是一种行为型模式,通过引入一个访问者类,能够动态地为元素类的操作提供不同的算法。这种设计模式特别适用于处理一个对象结构(如集合或组合结构)上的操作时,需要根据不同的访问者改变执行方式。

操作说明

访问者模式的核心思想是:将操作的执行从元素类的对象中抽离出来,转移到访问者类中。具体来说,元素类(Element)通过接收一个访问者(Visitor)对象,并调用访问者定义的相关操作(如visit方法)。这样做的好处是,可以在不修改元素类结构的情况下,灵活地为元素提供新的操作行为。

设计目标

访问者模式的主要目的是为一个对象结构增加新的能力。传统的设计模式中,这种需求通常采取了策略模式(Strategy Pattern)或状态模式(State Pattern)。而访问者模式则提供了更灵活的解决方案,特别适用于需要遍历对象结构时的行为扩展。

类结构

根据访问者模式的定义,通常需要以下几个角色:

  • Visitor:访问者类,声明了对所有元素类型的操作定义,即visit方法。
  • ConcreteVisitor:具体访问者,实现访问者类的操作,并根据需要记录或处理相关数据。
  • ObjectStructure:对象结构,可以是单个元素,也可以是一个容器(如树结构或图结构)。
  • Element:元素接口,定义了一个接受访问者的操作方法。
  • 在实际应用中,元素往往会组合成一个复杂的结构。例如,一个CustomerGroup类可以包含多个Customer对象,每个Customer对象又可以包含多个Order对象,每个Order对象又可以包含多个Item对象。这种层级结构的组合元素需要通过访问者模式来统一处理。

    实现示例

    假设我们有一个CustomerGroup对象,里面包含多个Customer对象。我们可以定义一个GeneralReport类作为访问者,用于统计每个Customer、Order和Item的数量。以下是实现代码的简要描述:

    interface Element {    void accept(Visitor visitor);}class CustomerGroup {    private List
    customers = new ArrayList<>(); void accept(Visitor visitor) { for (Customer customer : customers) { customer.accept(visitor); } } void addCustomer(Customer customer) { customers.add(customer); }}class Customer implements Element { private String name; private List
    orders = new ArrayList<>(); Customer(String name) { this.name = name; } String getName() { return name; } void addOrder(Order order) { orders.add(order); } public void accept(Visitor visitor) { visitor.visit(this); for (Order order : orders) { order.accept(visitor); } }}class Order implements Element { private String name; private List
    items = new ArrayList<>(); Order(String name) { this.name = name; } Order(String name, String itemName) { this.name = name; this.addItem(new Item(itemName)); } String getName() { return name; } void addItem(Item item) { items.add(item); } public void accept(Visitor visitor) { visitor.visit(this); for (Item item : items) { item.accept(visitor); } }}class Item implements Element { private String name; Item(String name) { this.name = name; } String getName() { return name; } public void accept(Visitor visitor) { visitor.visit(this); }}interface Visitor { void visit(Customer customer); void visit(Order order); void visit(Item item);}class GeneralReport implements Visitor { private int customersNo = 0; private int ordersNo = 0; private int itemsNo = 0; public void visit(Customer customer) { System.out.println(customer.getName()); customersNo++; } public void visit(Order order) { System.out.println(order.getName()); ordersNo++; } public void visit(Item item) { System.out.println(item.getName()); itemsNo++; } void displayResults() { System.out.println("Number of customers: " + customersNo); System.out.println("Number of orders: " + ordersNo); System.out.println("Number of items: " + itemsNo); }}class Client { public static void main(String[] args) { Customer customer1 = new Customer("customer1"); customer1.addOrder(new Order("order1", "item1")); customer1.addOrder(new Order("order2", "item1")); customer1.addOrder(new Order("order3", "item1")); Order order = new Order("order_a"); order.addItem(new Item("item_a1")); order.addItem(new Item("item_a2")); order.addItem(new Item("item_a3")); Customer customer2 = new Customer("customer2"); customer2.addOrder(order); CustomerGroup customers = new CustomerGroup(); customers.addCustomer(customer1); customers.addCustomer(customer2); GeneralReport visitor = new GeneralReport(); customers.accept(visitor); visitor.displayResults(); }}

    示例输出

    运行上述代码会输出如下结果:

    customer1order1item1order2item1order3item1customer2order_aitem_a1item_a2item_a3

    Number of customers: 2
    Number of orders: 4
    Number of items: 6

    实现工具

    如果你使用的是Java,可以参考以下JDK工具:

  • javax.lang.model.element.Elementjavax.lang.model.element.ElementVisitor
  • javax.lang.model.type.TypeMirrorjavax.lang.model.type.TypeVisitor
  • 这些工具可以帮助你在Java中更方便地处理代码元素和类型信息,但大多数情况下,手动实现访问者模式已经足够。但如果你需要更高级别的代码分析功能,JDK提供的工具可以提供更强大的支持。

    转载地址:http://pdhiz.baihongyu.com/

    你可能感兴趣的文章
    mysql 权限登录问题:ERROR 1045 (28000): Access denied for user ‘root‘@‘localhost‘ (using password: YES)
    查看>>
    MYSQL 查看最大连接数和修改最大连接数
    查看>>
    MySQL 查看有哪些表
    查看>>
    mysql 查看锁_阿里/美团/字节面试官必问的Mysql锁机制,你真的明白吗
    查看>>
    MySql 查询以逗号分隔的字符串的方法(正则)
    查看>>
    MySQL 查询优化:提速查询效率的13大秘籍(避免使用SELECT 、分页查询的优化、合理使用连接、子查询的优化)(上)
    查看>>
    mysql 查询,正数降序排序,负数升序排序
    查看>>
    MySQL 树形结构 根据指定节点 获取其下属的所有子节点(包含路径上的枝干节点和叶子节点)...
    查看>>
    mysql 死锁 Deadlock found when trying to get lock; try restarting transaction
    查看>>
    mysql 死锁(先delete 后insert)日志分析
    查看>>
    MySQL 死锁了,怎么办?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 深度分页性能急剧下降,该如何优化?
    查看>>
    MySQL 添加列,修改列,删除列
    查看>>
    mysql 添加索引
    查看>>
    MySQL 添加索引,删除索引及其用法
    查看>>
    MySQL 用 limit 为什么会影响性能?
    查看>>
    MySQL 用 limit 为什么会影响性能?有什么优化方案?
    查看>>
    MySQL 用户权限管理:授权、撤销、密码更新和用户删除(图文解析)
    查看>>
    mysql 用户管理和权限设置
    查看>>