博客
关于我
访问者模式
阅读量: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/

    你可能感兴趣的文章
    Luogu2973:[USACO10HOL]赶小猪
    查看>>
    mabatis 中出现&lt; 以及&gt; 代表什么意思?
    查看>>
    Mac book pro打开docker出现The data couldn’t be read because it is missing
    查看>>
    MAC M1大数据0-1成神篇-25 hadoop高可用搭建
    查看>>
    mac mysql 进程_Mac平台下启动MySQL到完全终止MySQL----终端八步走
    查看>>
    Mac OS 12.0.1 如何安装柯美287打印机驱动,刷卡打印
    查看>>
    MangoDB4.0版本的安装与配置
    查看>>
    Manjaro 24.1 “Xahea” 发布!具有 KDE Plasma 6.1.5、GNOME 46 和最新的内核增强功能
    查看>>
    mapping文件目录生成修改
    查看>>
    MapReduce程序依赖的jar包
    查看>>
    mariadb multi-source replication(mariadb多主复制)
    查看>>
    MariaDB的简单使用
    查看>>
    MaterialForm对tab页进行隐藏
    查看>>
    Member var and Static var.
    查看>>
    memcached高速缓存学习笔记001---memcached介绍和安装以及基本使用
    查看>>
    memcached高速缓存学习笔记003---利用JAVA程序操作memcached crud操作
    查看>>
    Memcached:Node.js 高性能缓存解决方案
    查看>>
    memcache、redis原理对比
    查看>>
    memset初始化高维数组为-1/0
    查看>>
    Metasploit CGI网关接口渗透测试实战
    查看>>