返回顶部
首页 > 资讯 > 后端开发 > Python >Java设计模式之访问者模式
  • 253
分享到

Java设计模式之访问者模式

Java设计模式访问者模式 2022-11-13 18:11:39 253人浏览 独家记忆

Python 官方文档:入门教程 => 点击学习

摘要

大多数情况下你不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了,这是设计模式创始人的原话。可以看出应用场景比较少,但需要它的时候是不可或缺的,这篇文章就开始学习最后一个

大多数情况下你不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了,这是设计模式创始人的原话。可以看出应用场景比较少,但需要它的时候是不可或缺的,这篇文章就开始学习最后一个设计模式——访问者模式。

一、概念理解

访问者模式概念:封装作用于某对象结构中的各元素的操作,它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。

通俗的解释就是,系统中有一些固定结构的对象(元素),在其内部提供一个accept()方法用来接受访问者对象的访问,不同的访问者对同一元素的访问内容不同,所以使得相同的元素可以产生不同的元素结果。

比如在一个人事管理系统中,有多个工种的员工和多个老板,不同的老板对同一个员工的关注点是不同的,CTO可能关注的就是技术,CEO可能更注重绩效。

员工就是一个稳定的元素,老板就是变化的,对应概念就是:封装员工的一些操作,可以在不改变员工类的前提下,增加新的老板访问同一个员工。

在访问者模式中包含五个角色,抽象元素、具体元素、抽象访问者、具体访问者、结构元素。

抽象元素:定义一个接受访问的方法accept,参数为访问者对象。

具体元素:提供接受访问者访问的具体实现调用访问者的访问visit,并定义额外的数据操作方法。

抽象访问者:这个角色主要是定义对具体元素的访问方法visit,理论上来说方法数等于元素(固定类型的对象,也就是被访问者)个数。

具体访问者:实现对具体元素的访问visit方法,参数就是具体元素。

结构对象:创建一个数组用来维护元素,并提供一个方法访问所有的元素。

二、案例实现

在一个公司有干活的工程师和管理者,也有抓技术的CTO和管绩效的CEO,CTO和CEO都会访问管理员和工程师,当公司来了新的老板,只需要增加访问者即可。

工程师和管理者就是元素、公司就是结构体、CEO、CTO就是访问者。

抽象元素:


public interface ElementAbstract {
    void accept(VisitorAbstract visitor);
}

具体元素-工程师:


public class ElementEngineer implements ElementAbstract {

    private String name;

    private int kpi;

    ElementEngineer(String name){
        this.name = name;
        this.kpi = new Random().nextInt(10);
    }

    public String getName() {
        return name;
    }

    public int getKpi() {
        return kpi;
    }


    @Override
    public void accept(VisitorAbstract visitor) {
        visitor.visit(this);
    }

    public int getCodeLineTotal(){
        return this.kpi * 1000000;
    }
}

具体元素-管理者:


public class ElementManager implements ElementAbstract {
    private String name;

    private int kpi;

    ElementManager(String name){
        this.name = name;
        this.kpi = new Random().nextInt(10);
    }

    public String getName() {
        return name;
    }

    public int getKpi() {
        return kpi;
    }

    @Override
    public void accept(VisitorAbstract visitor) {
        visitor.visit(this);
    }

    public int getProductNum(){
        return this.kpi * 10;
    }

}

抽象访问者:


public interface VisitorAbstract {
    void visit(ElementEngineer engineer);

    void visit(ElementManager manager);
}

具体访问者-CEO


public class VisitorCEO implements VisitorAbstract {
    @Override
    public void visit(ElementEngineer engineer) {
        System.out.println("工程师:" + engineer.getName() + "KPI:" + engineer.getKpi());
    }

    @Override
    public void visit(ElementManager manager) {
        System.out.println("经理:" + manager.getName() + "KPI:" + manager.getKpi() + " 今年共完成项目:" + manager.getProductNum() + "个");
    }
}

具体访问者-CTO


public class VisitorCTO implements VisitorAbstract {
    @Override
    public void visit(ElementEngineer engineer) {
        System.out.println("工程师:" + engineer.getName() + " 今年代码量" + engineer.getCodeLineTotal() + "行");
    }

    @Override
    public void visit(ElementManager manager) {
        System.out.println("经理:" + manager.getName() + " 今年共完成项目:" + manager.getProductNum() + "个");
    }
}

结构体:


public class Structure {
    List<ElementAbstract> list = new ArrayList<>();

    public Structure addEmployee(ElementAbstract employee){
        list.add(employee);
        return this;
    }

    public void report(VisitorAbstract visitor){
        list.forEach(employee -> {
            employee.accept(visitor);
        });
    }

}

客户端:


public class Client {
    public static void main(String[] args) {
        //元素对象
        ElementEngineer engineerZ = new ElementEngineer("小张");
        ElementEngineer engineerW = new ElementEngineer("小王");
        ElementEngineer engineerL = new ElementEngineer("小李");

        ElementManager managerZ = new ElementManager("张总");
        ElementManager managerW = new ElementManager("王总");
        ElementManager managerL = new ElementManager("李总");

        //结构体对象
        Structure structure = new Structure();
        structure.addEmployee(engineerZ).addEmployee(engineerW).addEmployee(engineerL).addEmployee(managerZ).addEmployee(managerW).addEmployee(managerL);
        structure.report(new VisitorCTO());
        System.out.println("---------------------------------------");
        structure.report(new VisitorCEO());


    }
}

访问者不愧是最难的设计模式,方法间的调用错综复杂,日常开发的使用频率很低,很多程序员宁可代码写的麻烦一点也不用这种设计模式,但是作为学习者就要学习各种设计模式了。

三、访问者模式在jdk中的应用

JDK的NIO中的 FileVisitor 接口采用的就是访问者模式。

在早期的 Java 版本中,如果要对指定目录下的文件进行遍历,必须用递归的方式来实现,这种方法复杂且灵活性不高。

Java 7 版本后,Files 类提供了 walkFileTree() 方法,该方法可以很容易的对目录下的所有文件进行遍历,需要 Path、FileVisitor 两个参数。其中,Path 是要遍历文件的路径,FileVisitor 则可以看成一个文件访问器,源码如下。

FileVisitor 主要提供了 4 个方法,且返回结果的都是 FileVisitResult 对象值,用于决定当前操作完成后接下来该如何处理。FileVisitResult 是一个枚举类,代表返回之后的一些后续操作,源码如下。

FileVisitResult 主要包含 4 个常见的操作。

  • FileVisitResult.CONTINUE:这个访问结果表示当前的遍历过程将会继续。
  • FileVisitResult.SKIP_SIBLINGS:这个访问结果表示当前的遍历过程将会继续,但是要忽略当前文件/目录的兄弟节点。
  • FileVisitResult.SKIP_SUBTREE:这个访问结果表示当前的遍历过程将会继续,但是要忽略当前目录下的所有节点。
  • FileVisitResult.TERMINATE:这个访问结果表示当前的遍历过程将会停止。

通过访问者去遍历文件树会比较方便,比如查找文件夹内符合某个条件的文件或者某一天内所创建的文件,这个类中都提供了相对应的方法。它的实现也非常简单,代码如下。

在JDK的应用中我们提供的文件就看做是一个稳定元素,对应访问者模式中的抽象元素;而Files.walkFileTree()方法中的FileVisitor 参数就可看做是角色中的访问者。

四、访问者模式中的伪动态双分派

访问者模式中有一个重要的概念叫:伪动态双分派。

我们一步一步解读它的含义,什么叫分派?根据对象的类型而对方法进行的选择,就是分派(Dispatch)。

发生在编译时的分派叫静态分派,例如重载(overload),发生在运行时的分派叫动态分派,例如重写(overwrite)。

其中分派又分为单分派和多分派。

单分派:依据单个变量进行方法的选择就叫单分派,Java 动态分派(重写)只根据方法的接收者一个变量进行分配,所以其是单分派。

多分派:依据多个变量进行方法的选择就叫多分派,Java 静态分派(重载)要根据方法的接收者与参数这两个变量进行分配,所以其是多分派。

理解了概念我们接着看我们的案例:

 @Override
    public void accept(VisitorAbstract visitor) {
        visitor.visit(this);
    }

我们案例中的accept方法,是由元素的运行时类型决定的,应该是属于动态单分派。

我们接着看 visitor.visit(this)又是一次动态单分派,两次动态单分派实现了双分派的效果,所以称为伪动态双分派。

这个概念理解就好,实际应用中知不知道这玩意都不影响。

五、总结

当你有个类,里面的包含各种类型的元素,这个类结构比较稳定,不会经常增删不同类型的元素。而需要经常给这些元素添加新的操作的时候,考虑使用此设计模式。

适用对象结构比较稳定每增加一个元素访问者都要大变动,但加新的操作很简单。集中相关的操作、分离无关的操作。

缺点只有两个字-复杂,号称是最复杂的设计模式。

到此这篇关于Java设计模式之访问者模式的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: Java设计模式之访问者模式

本文链接: https://lsjlt.com/news/169827.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Java设计模式之访问者模式
    大多数情况下你不需要访问者模式,但当一旦需要访问者模式时,那就是真的需要它了,这是设计模式创始人的原话。可以看出应用场景比较少,但需要它的时候是不可或缺的,这篇文章就开始学习最后一个...
    99+
    2022-11-13
    Java 设计模式 访问者模式
  • Java设计模式之java访问者模式详解
    目录介绍定义及使用场景UML类图角色财务案例个人心得体会静态分派以及动态分派静态分派动态分派访问者模式中的伪动态双分派 对访问者模式的一些思考总结优点缺点适用性参考文章总结介绍 ...
    99+
    2024-04-02
  • 深入理解Java设计模式之访问者模式
    目录一、什么是访问者模式二、访问者模式的结构三、访问者模式的使用场景四、访问者模式的优缺点五、访问者模式的实现总结一、什么是访问者模式 定义:表示一个作用于其对象结构中的各元素的操作...
    99+
    2024-04-02
  • 轻松掌握python设计模式之访问者模式
    本文实例为大家分享了python访问者模式代码,供大家参考,具体内容如下 """访问者模式""" class Node(object): pass class A(Node): pass c...
    99+
    2022-06-04
    模式 访问者 轻松
  • .Net行为型设计模式之访问者模式(Visitor)
    目录一、动机(Motivate)二、意图(Intent)三、结构图(Structure)四、模式的组成五、访问者模式的代码实现六、访问者模式的实现要点:(1)、访问者模式的主要优点有...
    99+
    2024-04-02
  • Java设计模式之中介者模式
    在我们实际业务中,可能存在多个类之间相互调用,形成了一个复杂的网状结构。这时候就需要有一种模式去“捋顺”他们之间的关系,引出一个中间者让类之间不再相互调用,该...
    99+
    2022-11-13
    Java 设计模式 中介者模式
  • Java设计模式之建造者模式
    本文由老王家组装电脑引出——建造者设计模式,详细介绍建造者模式的基本概念和实现代码,为了便于理解建造者模式,我们会对实际应用中的典型案例进行介绍。最后对比工厂...
    99+
    2024-04-02
  • Java设计模式之观察者模式
    目录一、观察者模式的定义和特点二、观察者模式的结构三、代码实例代码示例总结 一、观察者模式的定义和特点 观察者模式的定义: 指多个对象间存在一对多的依赖关系,当一个对象的状态发生改...
    99+
    2024-04-02
  • Java设计模式之观察者模式(Observer模式)
    目录一、观察者模式是什么?二、模式分析2.1 四个角色2.2 案例三、观察者模式的优缺点四、总结一、观察者模式是什么? 当对象间存在一对多关系时,则使用观察者模式(Observer ...
    99+
    2024-04-02
  • Python 设计模式行为型访问者模式
    目录一、访问者模式(Visitor Pattern)二、应用场景三、代码示例一、访问者模式(Visitor Pattern) 数据结构中保存着许多元素,当我们希望改变一种对元素的处理...
    99+
    2024-04-02
  • Java设计模式之访问者模式使用场景及代码示例
    Java设计模式访问者模式模式概念访问者模式表示一个作用于某对象结构中的各元素的操作,它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。访问者模式适用于数据结构相对稳定算法又易变化的系统,若系统数据结构对象易于变化,则不适合使用...
    99+
    2023-05-30
    java 访问者模式 ava
  • Java设计模式之java装饰者模式详解
    目录介绍角色示例代码星巴克咖啡的例子方案一方案二 :将调料内置到Drink类中方案三:装饰者模式代码演示装饰者模式的简化透明性的要求半透明的装饰模式装饰模式的优点装饰模式的缺点装饰模...
    99+
    2024-04-02
  • Java设计模式之java中介者模式详解
    目录引言介绍角色数据库同步数据案例不使用中介者模式的数据同步方案,各数据源维护各自的同步作业其实这样已经实现了我们的需求,但是存在一些问题中介者模式来重构,将数据同步的功能迁移到中介...
    99+
    2024-04-02
  • Java设计模式之java观察者模式详解
    目录引言介绍角色原理类图微信订阅号的案例总结优点缺点适用场景观察者模式的典型应用JDK 提供的观察者接口Guava EventBus 中的观察者模式Spring Applicatio...
    99+
    2024-04-02
  • 设计模式之建造者模式
    文章目录 盖房项目需求传统方式解决盖房需求传统方式的问题分析建造者模式概述是建造者模式的四个角色建造者模式原理类图建造者模式的注意事项和细节 盖房项目需求 需要建房子:这一过程为打桩、砌墙、封顶房子有各种各样的,比如普通房,高楼...
    99+
    2023-08-30
    设计模式
  • Java设计模式之装饰者模式详解
    目录具体代码:Person:Student:Doctor:DecoratePerson:ShoeDecorate:DressDecorate:总结 装饰器模式(Decorator P...
    99+
    2024-04-02
  • 设计模式系列之访问者模式的优点有哪些
    本篇内容主要讲解“设计模式系列之访问者模式的优点有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“设计模式系列之访问者模式的优点有哪些”吧!基本介绍访问者模式...
    99+
    2024-04-02
  • 怎么深入理解Java设计模式中的访问者模式
    怎么深入理解Java设计模式中的访问者模式,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。一、什么是访问者模式定义:表示一个作用于其对象结构中的各元素的操作,它使你可以在不改变各...
    99+
    2023-06-25
  • java设计模式:建造者模式之生产线
    目录什么是建造者模式建造者模式中的角色产品角色(Product)抽象建造者(Builder)具体建造者角色(ConcreteBuilder)导演者角色(Director)最终测试总结...
    99+
    2024-04-02
  • javascript设计模式之订阅者模式
    目录一. 初识代理模式二. 代理模式的实现思想三. 代理模式分类四. 虚拟代理模式的实际运用五. 代理的使用意义及要求六. 总结一. 初识代理模式 代理模式是为一个对象提供一个代用品...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作