【Java设计模式】非循环访问者模式:简化对象交互

文章目录

【Java设计模式】非循环访问者模式:简化对象交互

一、概述

在Java开发中,设计模式是提高代码质量和可维护性的重要工具。本文将介绍非循环访问者模式(Acyclic Visitor Pattern),包括其意图、详细解释、编程示例、类图、适用场景、教程、优点和权衡以及相关设计模式。同时,还将提供示例代码的下载链接,方便读者进行学习和实践。

二、非循环访问者设计模式的意图

Java中的非循环访问者模式将操作从对象层次结构中解耦,为各种应用提供了灵活的设计。

三、非循环访问者模式的详细解释及实际示例

  1. 实际示例
    • 一个类似的现实世界中的非循环访问者模式的例子是博物馆导游系统,展示了这种设计模式的实际应用。想象一个博物馆,里面有各种展品,如绘画、雕塑和历史文物。博物馆有不同类型的导游(音频导游、人工导游、虚拟现实导游),它们为每个展品提供信息。每当引入新的导游类型时,不是修改展品,而是每个导游实现一个接口来访问不同的展品类型。这样,博物馆可以添加新类型的导游,而无需更改现有的展品,确保系统保持可扩展性和可维护性,而不会形成任何依赖循环。
  2. 通俗解释
    • 非循环访问者模式允许在不修改现有类层次结构的情况下向其添加功能。
  3. Wiki解释
    • 非循环访问者模式允许向现有的类层次结构添加新功能,而不会影响这些层次结构,并且不会创建GangOfFour访问者模式中固有的依赖循环。

四、Java中非循环访问者模式的编程示例

在这个Java示例中,我们有一个调制解调器类的层次结构,展示了非循环访问者模式。这个层次结构中的调制解调器需要根据过滤标准(是否与Unix或DOS兼容的调制解调器)被外部算法访问。

  1. 首先是Modem层次结构。
java 复制代码
public abstract class Modem {
    public abstract void accept(ModemVisitor modemVisitor);
}
public class Zoom extends Modem {
    // 其他属性和方法...
    @Override
    public void accept(ModemVisitor modemVisitor) {
        if (modemVisitor instanceof ZoomVisitor) {
            ((ZoomVisitor) modemVisitor).visit(this);
        } else {
            LOGGER.info("Only ZoomVisitor is allowed to visit Zoom modem");
        }
    }
}
public class Hayes extends Modem {
    // 其他属性和方法...
    @Override
    public void accept(ModemVisitor modemVisitor) {
        if (modemVisitor instanceof HayesVisitor) {
            ((HayesVisitor) modemVisitor).visit(this);
        } else {
            LOGGER.info("Only HayesVisitor is allowed to visit Hayes modem");
        }
    }
}
  1. 接下来是ModemVisitor层次结构。
java 复制代码
public interface ModemVisitor {
}
public interface HayesVisitor extends ModemVisitor {
    void visit(Hayes hayes);
}
public interface ZoomVisitor extends ModemVisitor {
    void visit(Zoom zoom);
}
public interface AllModemVisitor extends ZoomVisitor, HayesVisitor {
}
public class ConfigureForDosVisitor implements AllModemVisitor {
    // 其他属性和方法...
    @Override
    public void visit(Hayes hayes) {
        LOGGER.info(hayes + " used with Dos configurator.");
    }
    @Override
    public void visit(Zoom zoom) {
        LOGGER.info(zoom + " used with Dos configurator.");
    }
}
public class ConfigureForUnixVisitor implements ZoomVisitor {
    // 其他属性和方法...
    @Override
    public void visit(Zoom zoom) {
        LOGGER.info(zoom + " used with Unix configurator.");
    }
}
  1. 最后是访问者的实际操作。
java 复制代码
public static void main(String[] args) {
    var conUnix = new ConfigureForUnixVisitor();
    var conDos = new ConfigureForDosVisitor();
    var zoom = new Zoom();
    var hayes = new Hayes();
    hayes.accept(conDos); // Hayes调制解调器与Dos配置器
    zoom.accept(conDos); // Zoom调制解调器与Dos配置器
    hayes.accept(conUnix); // Hayes调制解调器与Unix配置器
    zoom.accept(conUnix); // Zoom调制解调器与Unix配置器   
}

程序输出:

09:15:11.125 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForDosVisitor -- Hayes modem used with Dos configurator.
09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForDosVisitor -- Zoom modem used with Dos configurator.
09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.Hayes -- Only HayesVisitor is allowed to visit Hayes modem
09:15:11.127 [main] INFO com.iluwatar.acyclicvisitor.ConfigureForUnixVisitor -- Zoom modem used with Unix configurator.

五、非循环访问者模式类图

六、Java中何时使用非循环访问者模式

该模式可用于以下情况:

  1. 当需要向现有层次结构添加新功能,而无需更改或影响该层次结构时。
  2. 当有一些函数在层次结构上操作,但不属于该层次结构本身时。例如,ConfigureForDOS / ConfigureForUnix / ConfigureForX问题。
  3. 当需要根据对象的类型对其执行非常不同的操作时。
  4. 当被访问的类层次结构将经常用Element类的新派生类扩展时。
  5. 当Element的派生类的重新编译、重新链接、重新测试或重新分发非常昂贵时。

八、非循环访问者模式的优点和权衡

  1. 优点
    • 可扩展:可以轻松添加新操作,而无需更改对象结构。
    • 解耦:减少了对象与对它们的操作之间的耦合。
    • 无依赖循环:确保无环依赖,提高了可维护性并降低了复杂性。
  2. 权衡
    • 增加复杂性:可能会因为需要多个访问者接口而引入额外的复杂性。
    • 维护开销:修改对象层次结构需要更新所有访问者。

十一、源码下载

https://download.csdn.net/download/weixin_42545951/89679437

通过本文的介绍,相信大家对Java中的非循环访问者模式有了更深入的了解。在实际开发中,合理运用该模式可以提高代码的灵活性和可扩展性,同时降低代码的耦合性,为构建高质量的软件系统提供有力支持。

相关推荐
菜菜-plus2 分钟前
java 设计模式 模板方法模式
java·设计模式·模板方法模式
萨达大3 分钟前
23种设计模式-模板方法(Template Method)设计模式
java·c++·设计模式·软考·模板方法模式·软件设计师·行为型设计模式
tian-ming4 分钟前
(十八)JavaWeb后端开发案例——会话/yml/过滤器/拦截器
java·开发语言·前端
不能只会打代码8 分钟前
大学课程项目中的记忆深刻 Bug —— 一次意外的数组越界
java·github·intellij-idea·话题博客
快意咖啡~14 分钟前
java.nio.charset.MalformedInputException: Input length = 1
java·开发语言·nio
IT枫斗者41 分钟前
如何解决Java EasyExcel 导出报内存溢出
java·服务器·开发语言·网络·分布式·物联网
爱编程的小生43 分钟前
Easyexcel(4-模板文件)
java·excel
求积分不加C44 分钟前
Kafka怎么发送JAVA对象并在消费者端解析出JAVA对象--示例
java·分布式·kafka·linq
2401_857636391 小时前
实验室管理平台:Spring Boot技术构建
java·spring boot·后端
问窗1 小时前
微服务中Spring boot的包扫描范围
java·spring boot·微服务