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日

相关文章

  • 超级全面的PHP面试题整理集合第1/2页

    下面是详细的攻略: 第1/2页页面介绍 这是一篇关于PHP面试题的文章,分成1/2页展示,第一页包含了50道PHP面试题,第二页包含了另外50道PHP面试题。对于准备面试的PHP开发人员来说是一份不错的复习资料。该页面的排版清晰简洁,每个问题答案都有详细的解释,更新时间较新,适合PHP初级和高级开发人员进行参考。 页面内容分析 该页面的内容主要由50道PHP…

    Java 2023年6月15日
    00
  • Java进阶之FileUpload完成上传的实例

    Java进阶之FileUpload完成上传的实例 File Upload(文件上传)是Web应用程序中常用的功能之一,可以让用户将自己的文件上传到服务器。本文将介绍如何使用Java来实现文件上传功能。 实现流程 1.创建表单 首先,在前端编写一个表单,用来选择要上传的文件: <form action="upload" method=…

    Java 2023年6月2日
    00
  • MyBatis执行动态SQL的方法

    MyBatis 是一款开源的持久化框架,支持动态 SQL 的执行,可以方便地编写灵活的 SQL 语句,本文将详细讲解 MyBatis 执行动态 SQL 的方法,包括以下内容: 动态 SQL 的概念与背景 MyBatis 中执行动态 SQL 的方法 MyBatis 中使用动态 SQL 的示例 1. 动态 SQL 的概念与背景 传统的 SQL 语句是静态的,不能…

    Java 2023年5月19日
    00
  • Java字符串的intern方法有何奥妙之处

    讲解Java字符串的intern方法 什么是intern方法 Java编程语言中,字符串是一种不可变对象,即一旦字符串对象创建之后,它的值就不能再发生变化。 在Java中,字符串的intern方法是一个产生常量池的方法。当一个Java程序中通过常量来创建字符串时,实际上可以理解为它会检查常量池中是否已经存在这个字符串对象,如果已经存在,则会返回常量池中该对象…

    Java 2023年5月27日
    00
  • Springboot如何使用Aspectj实现AOP面向切面编程

    下面我将为你详细讲解如何使用Aspectj实现AOP面向切面编程。 什么是AOP? AOP,全称为Aspect Oriented Programming,即面向切面编程。它是一种编程思想,与OOP(面向对象编程)相对。AOP的主要优势在于能够将系统中的横切关注点(例如日志输出、权限校验、事务管理等)与核心业务逻辑分离。从而方便开发复用性更强的组件。Aspec…

    Java 2023年5月19日
    00
  • 详解如何将JAR包发布到Maven中央仓库

    下面我将为你详细讲解如何将JAR包发布到Maven中央仓库。 第一步:创建Maven账号 在将JAR包发布到Maven中央仓库之前,你需要先到Maven官网上创建一个账号。如果你已经有了账号,可以跳过这一步。 第二步:将JAR包发布到本地仓库 在将JAR包发布到Maven中央仓库之前,我们需要先将JAR包发布到本地仓库进行测试和验证。以下是一些简单的步骤: …

    Java 2023年5月20日
    00
  • spring data JPA 中的多属性排序方式

    关于spring data JPA中的多属性排序方式,可以参考以下攻略: 1. 前言 在实际应用中,很多时候需要对某个数据实体类的多个属性进行排序,比如员工表中的工号、入职时间、salary等字段。Spring data JPA提供了很方便的方式来同时对多个属性进行排序。 2. 排序方式 在Spring Data JPA中,我们可以使用 OrderBy 注解…

    Java 2023年6月3日
    00
  • Java 使用Calendar计算时间的示例代码

    下面是关于Java使用Calendar计算时间的完整攻略。 简介 Java提供了大量的时间和日期处理类和方法,其中Calendar类是处理时间和日期计算非常常用的类之一。这个类被广泛地应用于Java应用程序中,特别是在必须处理复杂日期和时间计算情况下。 获取Calendar实例 在使用Calendar类前,需要先获取一个Calendar实例。通常情况下,可以…

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