【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)

简介: 【设计模式】JAVA Design Patterns——Acyclic Visitor(非循环访问者模式)

🔍目的


允许将新功能添加到现有的类层次结构中,而不会影响这些层次结构,也不会有四人帮访客模式中那样循环依赖的问题。


🔍解释

真实世界例子

我们有一个调制解调器类的层次结构。 需要使用基于过滤条件的外部算法(是Unix或DOS兼容的调制解调器)来访问此层次结构中的调制解调器。


通俗描述

非循环访问者允许将功能添加到现有的类层次结构中,而无需修改层次结构


维基百科

非循环访客模式允许将新功能添加到现有的类层次结构中,而不会影响这些层次结构,也不会创建四人帮访客模式中固有的循环依赖问题


程序示例

调制解调器的层次结构:

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");
    }
  }
}


调制解调器访问者类结构:

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.");
  }
}


代码实践

    var conUnix = new ConfigureForUnixVisitor();
    var conDos = new ConfigureForDosVisitor();
    var zoom = new Zoom();
    var hayes = new Hayes();
    hayes.accept(conDos);
    zoom.accept(conDos);
    hayes.accept(conUnix);
    zoom.accept(conUnix);   


程序输出:

    // Hayes modem used with Dos configurator.
    // Zoom modem used with Dos configurator.
    // Only HayesVisitor is allowed to visit Hayes modem
    // Zoom modem used with Unix configurator.


🔍类图

image.png

Acyclic Visitor

🔍适用场景

  • 需要在现有层次结构中添加新功能而无需更改或影响该层次结构时。
  • 当某些功能在层次结构上运行,但不属于层次结构本身时。 例如 ConfigureForDOS / ConfigureForUnix / ConfigureForX问题。
  • 当您需要根据对象的类型对对象执行非常不同的操作时。
  • 当访问的类层次结构将经常使用元素类的新派生进行扩展时。
  • 当重新编译,重新链接,重新测试或重新分发派生元素非常昂贵时。


🔍结论

好处:

  • 类层次结构之间没有依赖关系循环。
  • 如果添加了新访客,则无需重新编译所有访客。
  • 如果类层次结构具有新成员,则不会导致现有访问者中的编译失败。


坏处:

  • 通过证明它可以接受所有访客,但实际上仅对特定访客感兴趣,从而违反Liskov的替代原则
  • 必须为可访问的类层次结构中的所有成员创建访问者的并行层次结构。


🔍扩展:

Liskov的替代原则

1.子类必须保留父类的行为

  子类应该继承并保持父类的所有属性和方法,以确保它们在同样的上下文中能够正常工作。

2.子类可以扩展父类的行为

  子类可以在不破坏父类原有行为的前提下,添加新的方法或属性来扩展功能。

3.子类覆盖父类方法时遵循约定

  如果子类需要覆盖(重写)父类的方法,那么子类的方法参数、返回类型和异常处理等要与父类方法保持一致,以确保可以无缝替换。

4.避免破坏类的不变性

  如果父类拥有某些不变性质或约束,子类也应当遵守这些约束,不应该破坏这些约定。

遵循里氏替换原则有助于构建更健壮、灵活且易于维护的代码。如果违反了这一原则,可能会导致意外的行为,使代码变得不稳定或难以理解。通过正确地应用里氏替换原则,可以确保你的代码在继承体系中保持稳定和一致。


07eede5202c04e0c824b65621209a01e.gif

相关文章
|
21天前
|
Java
Java的控制流程语句:深入理解条件语句、循环语句与跳转语句
Java的控制流程语句:深入理解条件语句、循环语句与跳转语句
25 1
|
24天前
|
设计模式 Java 数据库连接
【重温设计模式】代理模式及其Java示例
【重温设计模式】代理模式及其Java示例
|
27天前
|
设计模式 Java 数据库
【设计模式】JAVA Design Patterns——Converter(转换器模式)
转换器模式旨在实现不同类型间的双向转换,减少样板代码。它通过通用的Converter类和特定的转换器(如UserConverter)简化实例映射。Converter类包含两个Function对象,用于不同类型的转换,同时提供列表转换方法。当需要在逻辑上对应的类型间转换,或处理DTO、DO时,此模式尤为适用。
【设计模式】JAVA Design Patterns——Converter(转换器模式)
|
7天前
|
设计模式 存储 安全
Java中的23种设计模式
Java中的23种设计模式
9 1
|
17天前
|
Java 程序员
14. 【Java教程】Java 循环语句
14. 【Java教程】Java 循环语句
14 3
|
23天前
|
Java 数据处理
Java中do…while循环语句
Java中do…while循环语句
24 3
|
24天前
|
设计模式 安全 Java
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)
该文介绍了一种C++的编程技巧——奇异递归模板模式(CRTP),旨在让派生组件能继承基本组件的特定功能。通过示例展示了如何创建一个`Fighter`接口和`MmaFighter`类,其中`MmaFighter`及其子类如`MmaBantamweightFighter`和`MmaHeavyweightFighter`强制类型安全,确保相同重量级的拳手之间才能进行比赛。这种设计避免了不同重量级拳手间的错误匹配,编译时会报错。CRTP适用于处理类型冲突、参数化类方法和限制方法只对相同类型实例生效的情况。
【设计模式】JAVA Design Patterns——Curiously Recurring Template Pattern(奇异递归模板模式)
|
22天前
|
设计模式 存储 前端开发
Java的mvc设计模式在web开发中应用
Java的mvc设计模式在web开发中应用
|
22天前
|
存储 Java 数据库
Java中的do-while循环语句详解
Java中的do-while循环语句详解
|
22天前
|
存储 Java 程序员
深入解析Java中的foreach循环语句
深入解析Java中的foreach循环语句
17 0