首页 > 编程语言 >Java行为型设计模式-访问者模式(含二叉树场景示例)

Java行为型设计模式-访问者模式(含二叉树场景示例)

时间:2024-08-25 17:21:51浏览次数:11  
标签:示例 Visitor void 元素 Element 二叉树 设计模式 public 访问者

1. 访问者模式简介

访问者模式Visitor Pattern)是一种行为型设计模式其主要目的是将数据结构与数据操作解耦。用于将数据结构和在数据结构上的操作分离开来。‌这种模式允许在不修改数据结构的情况下,定义新的操作。

2. 访问者模式角色

访问者模式的主要角色包括:

2.1 抽象访问者(Visitor)角色

定义了对每一个元素访问的行为。这个角色的方法个数与元素类的个数相同,每个方法对应一个具体的元素类。

2.2 具体访问者(ConcreteVisitor)角色

实现了抽象访问者接口,定义了对每一个元素类访问时所产生的具体行为。

2.3 抽象元素(Element)角色

定义了一个接受访问者的方法(accept),意味着每一个元素都可以被访问者访问。

2.4 具体元素(ConcreteElement)角色

提供了接受访问方法的具体实现,通常使用访问者提供的方法来访问该元素类。

2.5 对象结构(Object Structure)角色

是一个具有容器性质或复合对象特性的类,含有一组元素,并可以迭代这些元素供访问者访问。

3. 访问者模式使用场景

访问者模式在处理复杂的数据结构和操作集合时非常有用,它能够有效地降低代码的耦合度,提高代码的可维护性可扩展性

访问者模式主要使用场景有这些:

  1. 在不修改原有类结构的情况下,为对象结构中的元素添加新的操作‌。当对象结构中的元素需要进行不同的操作,而且你不希望这些操作污染元素类时,可以使用访问者模式。这种情况下,通过访问者模式可以在不修改原有类结构的前提下,为对象添加新的操作,保持了原有类的封装性和稳定性‌。

  2. 处理数据结构稳定但操作经常变化的情况‌。当数据结构相对稳定,但经常需要变化或增加新的操作时,可以使用访问者模式。访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可以灵活变化而不影响元素的类‌。

  3. 处理不同操作涉及不同元素类型的情况‌。当不同的操作需要访问数据结构中不同类型的元素时,可以使用访问者模式。通过定义访问者接口和具体访问者类,可以实现针对不同元素类型的特定操作‌。

  4. 避免在元素类中增加新的操作导致类膨胀‌。当不希望在元素类中增加新的操作导致类膨胀时,可以使用访问者模式,将操作封装到独立的访问者类中。这样可以保持元素类的简洁和可维护性‌。

  5. 处理复杂的业务逻辑‌。在复杂的业务场景中,如电商系统、游戏比赛管理系统中,访问者模式可以用来处理不同对象之间的复杂关系和操作,提高代码的可扩展性和可维护性‌。

4. 访问者模式代码示例(教学示例)

以下是访问者模式简单的应用代码示例:

4.1 定义访问者接口

// 定义访问者接口
interface Visitor {
    void visit(ConcreteElementA element);
    void visit(ConcreteElementB element);
}

4.2 具体访问者实现

// 具体访问者实现
class ConcreteVisitor implements Visitor {
    public void visit(ConcreteElementA element) {
        // 实现对 ConcreteElementA 的操作
        System.out.println("操作 ConcreteElementA");
    }
 
    public void visit(ConcreteElementB element) {
        // 实现对 ConcreteElementB 的操作
        System.out.println("操作 ConcreteElementB");
    }
}

4.3 定义元素接口

// 定义元素接口
interface Element {
    void accept(Visitor visitor);
}

4.4 具体元素实现

// 具体元素实现
class ConcreteElementA implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}
 
class ConcreteElementB implements Element {
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
}

4.5 对象结构类定义

// 对象结构类
class ObjectStructure {
    private List<Element> elements = new ArrayList<>();
 
    public void attach(Element element) {
        elements.add(element);
    }
 
    public void detach(Element element) {
        elements.remove(element);
    }
 
    public void accept(Visitor visitor) {
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

4.6 客户端调用代码

// 客户端代码
public class Client {
    public static void main(String[] args) {
        ObjectStructure structure = new ObjectStructure();
        structure.attach(new ConcreteElementA());
        structure.attach(new ConcreteElementB());
 
        ConcreteVisitor visitor = new ConcreteVisitor();
        structure.accept(visitor);
    }
}

这个代码示例展示了如何在Java中实现访问者模式。它定义了一个Visitor接口和一个ConcreteVisitor具体实现,接着定义了Element接口和两个具体的Element实现类。ObjectStructure类用于维护元素集合,并允许访问者遍历这些元素。客户端代码创建了结构、元素、访问者,并展示了如何使用它们。

5. 访问者模式代码示例(二叉树查找)

以下是一个简单的Java使用访者模式的示例,假设我们有一个简单的二叉树结构,并且我们想要遍历这棵树并打印出所有的整数节点:

5.1 定义二叉树抽象元素接口

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

5.2 二叉树整数元素节点实现

// 元素的具体实现:整数节点
class IntegerNode implements Element {
    int value;
 
    public IntegerNode(int value) {
        this.value = value;
    }
 
    @Override
    public void accept(Visitor visitor) {
        visitor.visitInteger(this);
    }
 
    public int getValue() {
        return value;
    }
}

5.3 二叉树类型元素节点实现

// 元素的具体实现:二叉树
class BinaryTree implements Element {
    Element left;
    Element right;
 
    public BinaryTree(Element left, Element right) {
        this.left = left;
        this.right = right;
    }
 
    @Override
    public void accept(Visitor visitor) {
        visitor.visitBinaryTree(this);
    }
 
    public Element getLeft() {
        return left;
    }
 
    public Element getRight() {
        return right;
    }
}

5.4 二叉树节点访问者抽象接口

// 访问者接口
interface Visitor {
    void visitInteger(IntegerNode integerNode);
    void visitBinaryTree(BinaryTree binaryTree);
}

5.5 二叉树节点访问者实现类型

// 具体的访问者实现
class PrintVisitor implements Visitor {
    @Override
    public void visitInteger(IntegerNode integerNode) {
        System.out.println("Integer: " + integerNode.getValue());
    }
 
    @Override
    public void visitBinaryTree(BinaryTree binaryTree) {
        binaryTree.left.accept(this);
        binaryTree.right.accept(this);
    }
}

5.6 客户端代码

// 使用示例
public class VisitorPatternExample {
    public static void main(String[] args) {
        Element tree = new BinaryTree(
            new IntegerNode(5),
            new BinaryTree(
                new IntegerNode(3),
                new IntegerNode(8)
            )
        );
 
        Visitor printer = new PrintVisitor();
        tree.accept(printer);
    }
}

在这个例子中,Element接口定义了一个方法accept,它接受一个Visitor对象作为参数。Visitor接口定义了对所有可能的Element类型的访问方法。PrintVisitor类实现了Visitor接口,用于打印元素的内容。

main方法中,我们构建了一个二叉树,并使用PrintVisitor来遍历整棵树并打印出所有的整数节点。这个例子展示了如何使用访问者模式来处理一个具有不同类型节点的数据结构。

6. 访问者模式优缺点

访问者模式通过双重分派实现了这一目的,即将数据结构的处理方法从数据结构中分离出来。主要优缺点如下:

6.1 优点

  • 高扩展性‌:能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能。这意味着可以通过添加新的具体访问者类来扩展系统的功能,而不需要修改现有的元素类或对象结构‌。
  • 高复用性‌:可以通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。访问者模式允许对不同的元素执行不同的操作,同时保持对象结构的稳定性‌。
  • 灵活性‌:访问者模式将数据结构与作用于结构上的操作解耦,使得操作集合可以相对自由地演化而不影响系统的数据结构。这种解耦使得系统更加灵活,能够适应未来的变化‌。
  • 符合单一职责原则‌:访问者模式把相关的行为封装在一起,构成一个访问者,使每一个访问者的功能都比较单一。这有助于提高代码的可读性和可维护性‌。

6.2 缺点

  1. 增加新元素类困难‌:在访问者模式中,每增加一个新的元素类,都需要在每一个具体访问者类中增加相应的具体操作。这违背了“开闭原则”,即对扩展开放,对修改关闭的原则‌。
  2. 违反迪米特原则和依赖倒置原则‌:因为访问的具体目标对访问者类提供了具体的细节,这违反了迪米特原则和依赖倒置原则。这可能导致代码之间的耦合度较高,不利于维护和扩展‌。
  3. 修改具体目标改动不易‌:当需要对具体目标进行修改时,可能会影响到使用访问者模式的代码部分,因为访问者模式增加了系统的复杂性‌。

7. 总结

综上所述,访问者模式Visitor Pattern)是一种行为型设计模式。访问者模式在Java中提供了一种有效的方式来扩展系统的功能,同时保持对象结构的稳定性

访问者模式在处理复杂的数据结构和操作集合时非常有用,它能够有效地降低代码的耦合度,能极大提高代码的可维护性可扩展性

然而,它也有其固有的缺点,特别是在增加新元素类和修改现有元素时可能会遇到挑战。因此,在设计系统时,需要根据具体的需求和约束来决定是否使用访问者模式‌。

标签:示例,Visitor,void,元素,Element,二叉树,设计模式,public,访问者
From: https://blog.csdn.net/lilinhai548/article/details/141502946

相关文章

  • 高德地图SDK Android版开发 8 覆盖物示例2动画
    高德地图SDKAndroid版开发8覆盖物示例2动画前言动画相关的类和接口帧动画MarkerOptionsAnimation动画Animation类及其子类AnimationTranslateAnimationRotateAnimationAlphaAnimationScaleAnimationAnimationSetMarker动画示例界面布局MapMarkAnimate类常量成员变......
  • RabbitMQ 入门示例
    参考:BV15k4y1k7EpRabbitMQ相关概念及简述中简单介绍了RabbitMQ提供的6种工作模式。下面以简单模式为例,介绍RabbitMQ的使用。新建工程先新建Maven工程RabbitMQ作为父工程,在父工程下新建三个子模块:common:公共包producer:生产者consumer:消费者在三个模块中添加......
  • ensp 中 wlan 的配置过程和示例
    一、拓朴:要求:vlan20用于笔记本上网,使用Huawei信号,vlan30用于手机上网,使用Huawei-5G信号二、配置过程:        1、SW1基本配置:        起vlanbatch102030,10为管理vlan,20、30分别为办公vlan和guestvlan        到AC接口为trunk,允许vl......
  • linux下试验中间件canal的example示例-binlog日志的实时获取显示以及阿里巴巴中间件ca
    一、linux下试验中间件canal的example示例-binlog日志的实时获取显示    今天重装mysql后,进行了canal的再次试验,原来用的mysql5.7,今天重装直接换了5.6算了。反正测试服务器的mysql也不常用。canal启动后日志显示examplepreparetofindstartpositionjustshowmaste......
  • 基于SpringBoot的智慧党建系统+uniapp移动端+LW示例参考
    1.项目介绍技术栈+环境:SpringBoot+thymeleaf+uniapp+IDEA+Navicat+MySQL功能介绍:后端功能:首页管理(轮播图、通知公告、新闻管理)、用户管理(用户信息、用户反馈、用户订单、用户动态)、其他管理(题库管理、任务管理)移动端:学习模块、游戏学习模块、打卡签到、积分商城、问题咨......
  • 设计模式篇(DesignPattern - 前置知识 & 七大原则)(持续更新调整)
    目录前置知识一、什么是设计模式二、设计模式的目的七大原则原则一:单一职责原则一、案例一:交通工具问题1.问题分析2.解决思路2.1类级别单一职责2.2方法级别单一职责3.知识小结二、案例二:待更新原则二:接口隔离原则一、案例一:大接口拆分小接口1.问题分析2.......
  • 设计模式反模式:UML图示常见误用案例分析
    设计模式反模式:UML图示常见误用案例分析在软件开发过程中,设计模式(DesignPatterns)作为解决常见设计问题的最佳实践,被广泛地应用于提高代码质量和可维护性。然而,当这些设计模式被误用或滥用时,它们可能会变成反模式(Anti-Patterns),导致系统架构的复杂性增加,甚至引发一系列问题......
  • 秋招力扣Hot100刷题总结——二叉树
    二叉树相关的题目基本上都会使用递归,因此做二叉树的题目时首先使用递归,明确递归结束的条件。1.二叉树的层序遍历题目链接题目要求:给你二叉树的根节点root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。代码及思路使用队列存储每一层的节点,左边节点先......
  • 集合及数据结构第九节————树和二叉树
    系列文章目录集合及数据结构第九节————树和二叉树树和二叉树树型结构的概念树的概念树的表示形式(了解)树的应用二叉树的概念两种特殊的二叉树二叉树的性质二叉树的性质练习二叉树的存储二叉树的遍历二叉树的基本操作二叉树相关练习题文章目录系列文章目录集合及......
  • 游戏开发设计模式之责任链模式
    责任链模式(ChainofResponsibilityPattern)是一种行为型设计模式,它允许将请求沿着处理者链进行发送。每个处理者对象都有机会处理该请求,直到某个处理者决定处理该请求为止。概念与定义责任链模式的核心思想是将多个处理器以链式结构连接起来,使请求沿着链传递,直到有一个处理......