博客
关于我
访问者模式
阅读量: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中关于geometry类型的数据_空的时候如何插入处理_需用null_空字符串插入会报错_Cannot get geometry object from dat---MySql工作笔记003
    查看>>
    mysql中出现Incorrect DECIMAL value: '0' for column '' at row -1错误解决方案
    查看>>
    mysql中出现Unit mysql.service could not be found 的解决方法
    查看>>
    mysql中出现update-alternatives: 错误: 候选项路径 /etc/mysql/mysql.cnf 不存在 dpkg: 处理软件包 mysql-server-8.0的解决方法(全)
    查看>>
    Mysql中各类锁的机制图文详细解析(全)
    查看>>
    MySQL中地理位置数据扩展geometry的使用心得
    查看>>
    Mysql中存储引擎简介、修改、查询、选择
    查看>>
    Mysql中存储过程、存储函数、自定义函数、变量、流程控制语句、光标/游标、定义条件和处理程序的使用示例
    查看>>
    mysql中实现rownum,对结果进行排序
    查看>>
    mysql中对于数据库的基本操作
    查看>>
    Mysql中常用函数的使用示例
    查看>>
    MySql中怎样使用case-when实现判断查询结果返回
    查看>>
    Mysql中怎样使用update更新某列的数据减去指定值
    查看>>
    Mysql中怎样设置指定ip远程访问连接
    查看>>
    mysql中数据表的基本操作很难嘛,由这个实验来带你从头走一遍
    查看>>
    Mysql中文乱码问题完美解决方案
    查看>>
    mysql中的 +号 和 CONCAT(str1,str2,...)
    查看>>
    Mysql中的 IFNULL 函数的详解
    查看>>
    mysql中的collate关键字是什么意思?
    查看>>
    MySql中的concat()相关函数
    查看>>