Java访问者设计模式详细讲解

Java访问者设计模式详细讲解

什么是访问者设计模式?

访问者设计模式是一种行为型设计模式,它允许你将对象元素操作与其所在的对象分离开来,并将其封装在另一个对象中。通过这种方式,我们可以在不改变被访问对象的类的前提下,增加新的功能操作。访问者模式在实际应用中非常常见,例如在编译器中,AST(抽象语法树)节点经常会被访问者模式处理。

访问者设计模式的结构

  • Visitor(访问者):定义具体的访问行为,也称为操作类。
  • ConcreteVisitor(具体访问者):访问者实现类。
  • Element(元素):定义一个接受访问者的接口。
  • ConcreteElement(具体元素):元素实现类,实现接口定义的接收行为。
  • ObjectStructure(对象结构):可以是一个组合或集合,包含元素对象。

访问者模式的实现

我们现在来看一个简单的示例进行说明。假设我们有一个简单的电视机程序,电视机包含多个部分,包括电视机、桌面、音响等等。现在,我们想要访问每个部分并进行一些操作,这时我们可以使用访问者模式。

定义角色

我们来看一下这个示例中访问者设计模式的角色定义。

// 定义元素接口
public interface TvPart {
    public void accept(TvPartVisitor visitor);
}

// 定义元素实现
public class Tv implements TvPart {
    TvPart[] parts;

    public Tv(){
       parts = new TvPart[] {new Desktop(), new Speaker()};
    }

    public void accept(TvPartVisitor visitor) {
       for (int i = 0; i < parts.length; i++) {
           parts[i].accept(visitor);
       }
       visitor.visit(this);
    }
}

public class Desktop implements TvPart {
   public void accept(TvPartVisitor visitor) {
      visitor.visit(this);
   }
}

public class Speaker implements TvPart {
   public void accept(TvPartVisitor visitor) {
      visitor.visit(this);
   }
}

// 定义访问者接口
public interface TvPartVisitor {
   public void visit(Tv tv);
   public void visit(Desktop desktop);
   public void visit(Speaker speaker);
}

// 定义访问者实现类
public class TvVisitor implements TvPartVisitor {
   public void visit(Tv tv) {
      System.out.println("Visiting TV.");
   }

   public void visit(Desktop desktop) {
      System.out.println("Visiting Desktop.");
   }

   public void visit(Speaker speaker) {
      System.out.println("Visiting Speaker.");
   }
}

调用示例

我们现在来看一下,如何调用这个访问者设计模式的实现。

public class VisitorTest {
   public static void main(String[] args) {

      TvPart tv = new Tv();
      tv.accept(new TvVisitor());
   }
}

示例说明

在上述示例中,我们定义了访问者接口TvPartVisitor和元素接口TvPart。其中,元素接口中定义了一个参数为Visitor类型的接受访问者的方法。我们还要定义元素的实现类TvDesktopSpeaker,它们也实现了TvPart接口,同时它们也接受了Visitor的访问。另外,我们还定义了访问者的实现类TvVisitor,该访问者实现了TvPartVisitor接口,并且针对不同的元素类提供了不同的访问操作。最后,我们在VisitorTest类中调用了TvVisitor来访问Tv元素。

示例2:一个完整的访问者设计模式的例子

我们来看一个更加完整的示例。假设我们有一个游戏,里面包含了多个游戏区域。现在,我们想要针对不同的游戏区域,进行不同的操作,比如打印区域信息、计算区域有效面积等等。这个时候,我们可以使用访问者设计模式。

定义角色

// Element:定义一个访问者接受方法
public interface GameZone {
    void accept(GameZoneVisitor visitor);
}

// Element ElementA:实现访问者接受方法
public class WoodZone implements GameZone {
    private double width;
    private double length;

    public WoodZone(double width, double length) {
        this.width = width;
        this.length = length;
    }

    public void accept(GameZoneVisitor visitor) {
        visitor.visitWoodZone(this);
    }

    public double getWidth() {
        return width;
    }

    public double getLength() {
        return length;
    }
}


// Element ElementB:实现访问者接受方法
public class WaterZone implements GameZone {
    private double radius;

    public WaterZone(double radius) {
        this.radius = radius;
    }

    public void accept(GameZoneVisitor visitor) {
        visitor.visitWaterZone(this);
    }

    public double getRadius() {
        return radius;
    }
}

// Visitor:定义多个访问者方法
public interface GameZoneVisitor {
    void visitWoodZone(WoodZone woodZone);

    void visitWaterZone(WaterZone waterZone);
}

// Visitor VisitorA:实现多个访问者方法
public class PrintGameZoneVisitor implements GameZoneVisitor {
    public void visitWoodZone(WoodZone woodZone) {
        System.out.println("这是一个长方形小区域,长宽分别为: " + woodZone.getLength() + " "
            + woodZone.getWidth());
    }

    public void visitWaterZone(WaterZone waterZone) {
        System.out.println("这是一个圆形水域,半径为:" + waterZone.getRadius());
    }
}

// Visitor VisitorB:实现多个访问者方法
public class CalculateAreaVisitor implements GameZoneVisitor {
    double totalArea = 0;

    public void visitWoodZone(WoodZone woodZone) {
        totalArea += woodZone.getWidth() * woodZone.getLength();
    }

    public void visitWaterZone(WaterZone waterZone) {
        totalArea += Math.PI * Math.pow(waterZone.getRadius(), 2);
    }

    public double getTotalArea() {
        return totalArea;
    }
}

调用示例

我们现在来看一下,如何调用这个访问者设计模式的实现。

public class GameZoneTest {
    public static void main(String[] args) {
        GameZone[] zones = { new WoodZone(3, 2), new WaterZone(1.5) };

        PrintGameZoneVisitor printVisitor = new PrintGameZoneVisitor();
        CalculateAreaVisitor areaVisitor = new CalculateAreaVisitor();

        for (GameZone zone : zones) {
            zone.accept(printVisitor);
            zone.accept(areaVisitor);
        }

        System.out.println("所有区域的有效面积:" + areaVisitor.getTotalArea());
    }
}

示例说明

在上述示例中,我们定义了元素接口GameZone,同时我们定义了两个元素类WoodZoneWaterZone,它们都实现了GameZone接口,并且在实现类中都实现了接受访问方法accept,用以接收不同的访问者操作。我们还定义了访问者接口GameZoneVisitor,并且我们在实现了访问者接口的PrintGameZoneVisitorCalculateAreaVisitor中,都实现了不同的访问操作。最后,在GameZoneTest类中,我们调用了这些访问者,并执行了相应的操作。

总的来说,访问者设计模式可以使得算法的不同实现与对象的结构分离开来,这样,算法就可以被独立的改变和重复利用了。虽然这个模式会增加代码的复杂度,但是,如果可能存在多种实现方式的情况下,访问者的模式会更为合适。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java访问者设计模式详细讲解 - Python技术站

(0)
上一篇 2023年5月26日
下一篇 2023年5月26日

相关文章

  • Java实现单人信息管理程序

    下面我将为你详细讲解“Java实现单人信息管理程序”的完整攻略。 1. 需求分析 在开始编写程序之前,我们需要确定具体的需求。本文中,我们需要实现单人信息管理程序,需要实现以下功能:1. 添加一个新的信息2. 查看所有信息3. 修改已有的信息4. 删除已有的信息 2. 数据结构设计 在确定需求之后,我们需要确定数据结构。这里我们使用Java中的ArrayLi…

    Java 2023年5月18日
    00
  • kaptcha验证码组件使用简介解析

    首先给出一份包含标题、正文内容和示例代码的markdown文本: Kaptcha验证码组件使用简介解析 Kaptcha是一款Java语言编写的验证码组件,可以非常方便地为Web应用添加验证码保护。它支持自定义验证码样式,包括验证码字符、字体、大小、颜色、背景等,同时还具备多语言支持、音频验证码功能以及代码简单等优点。 在下面的示例中,我们将详细讲解如何使用K…

    Java 2023年6月15日
    00
  • IDEA 启动 Tomcat 项目输出乱码的解决方法

    下面是关于“IDEA 启动 Tomcat 项目输出乱码的解决方法”的完整攻略: 1. 问题描述 在使用 IDEA 启动 Tomcat 项目时,控制台输出的内容是一些乱码,影响了开发和调试的效率。 2. 解决方法 2.1 修改 Tomcat 服务器配置 在 Tomcat 服务器配置中,添加一些 JVM 参数,来指定字符集和编码方式。 步骤如下: 在 IDEA …

    Java 2023年5月19日
    00
  • 浅谈几种Java自定义异常处理方式

    浅谈几种Java自定义异常处理方式 在Java中,异常是一种非常常见的错误类型,如果没有捕获和处理异常,程序很容易因为意外的错误而导致崩溃。Java允许我们自定义异常类型,来处理程序中特定的异常情况。本文将对几种Java自定义异常处理方式进行探讨,并提供示例代码来帮助读者加深对这些技术的理解。 自定义异常类 我们可以通过继承 Java 内置的异常类(Thro…

    Java 2023年5月20日
    00
  • Advanced SQL Injection with MySQL

    Advanced SQL Injection with MySQL是一种比较高级的SQL注入攻击方式,需要攻击者对SQL语言和MySQL数据库的运作方式非常熟悉。下面是一个完整的攻击步骤: 1. 了解目标网站的数据库类型和版本 在进行SQL注入攻击之前,我们需要了解目标网站所使用的数据库类型和版本。假设我们已经知道目标网站正在使用MySQL数据库,我们可以尝…

    Java 2023年6月16日
    00
  • 详解Java字节码编程之非常好用的javassist

    详解Java字节码编程之非常好用的javassist 前言 Java字节码是Java程序在编译过程中生成的中间代码,有些用户可能需要在程序运行时直接修改Java字节码,这就需要用到Java字节码编程技术。Java字节码编程技术使用非常广泛,涉及方面包括AOP、动态代理、字节码加密等。 在Java字节码编程中,有一个非常好用的工具库——javassist,它提…

    Java 2023年5月23日
    00
  • java实现秒表功能

    下面是Java实现秒表功能的完整攻略: 确定界面布局 首先,要确定秒表界面的布局,可以使用Swing包提供的JFrame、JLabel等组件。 一个简单的秒表GUI界面可以包含如下控件: 用于显示秒数的JLabel。 用于开始、停止、清零等操作的JButton。 (可选)用于记录计时时间的列表或文本框。 编写计时器逻辑 初始秒表面板布局完成后,需要编写计时器…

    Java 2023年5月20日
    00
  • Java 9 中的模块Module系统

    关于Java 9中的模块(Module)系统,这里为您整理了完整的攻略。请您仔细阅读以下文章。 什么是Module系统 Java 9中引入了一种新的概念——Module系统,来管理和组织代码。作为Java9中最重要的新特性之一,模块化系统的引入为我们开发、维护和交付大规模的Java应用程序提供了更多的选择和优化。 为什么引入Module系统 随着时间的推移,…

    Java 2023年5月24日
    00
合作推广
合作推广
分享本页
返回顶部