Java 中的无环访问者模式:简化对象交互
约 3 分钟
无环访问者设计模式的意图
Java 中的无环访问者模式将操作与对象层次结构解耦,为各种应用程序提供灵活的设计。
无环访问者模式的详细解释,附带现实世界中的例子
现实世界中的例子
Java 中无环访问者模式的类比现实世界中的例子是博物馆导览系统,展示了这种设计模式的实际应用。想象一个拥有绘画、雕塑和历史文物等各种展品的博物馆。该博物馆有不同类型的导览(语音导览、人工导览、虚拟现实导览)来提供有关每个展品的详细信息。与其每次引入新导览类型时都修改展品,不如让每个导览都实现一个接口来访问不同的展品类型。这样,博物馆就可以添加新类型的导览,而无需修改现有展品,确保系统保持可扩展性和可维护性,而不会形成任何依赖循环。
通俗地说
无环访问者允许向现有的类层次结构添加函数,而无需修改层次结构。
无环访问者模式允许向现有的类层次结构添加新函数,而不会影响这些层次结构,也不会创建四重奏访问者模式固有的依赖循环。
Java 中无环访问者的编程示例
在这个 Java 示例中,我们有一个调制解调器类的层次结构,它说明了无环访问者模式。这个层次结构中的调制解调器需要由一个基于过滤条件(是 Unix 还是 DOS 兼容调制解调器)的外部算法访问。
以下是 调制解调器
层次结构。
public abstract class Modem {
public abstract void accept(ModemVisitor modemVisitor);
}
public class Zoom extends Modem {
// Other properties and methods...
@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 {
// Other properties and methods...
@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 {
// Other properties and methods...
@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 {
// Other properties and methods...
@Override
public void visit(Zoom zoom) {
LOGGER.info(zoom + " used with Unix configurator.");
}
}
最后,以下是访问者在实际应用中的情况。
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 modem with Dos configurator
zoom.accept(conDos); // Zoom modem with Dos configurator
hayes.accept(conUnix); // Hayes modem with Unix configurator
zoom.accept(conUnix); // Zoom modem with Unix configurator
}
程序输出
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 中使用无环访问者模式
此模式可以用于
- 当您需要向现有层次结构添加新函数,而无需修改或影响该层次结构时。
- 当存在作用于层次结构的函数时,但这些函数本身并不属于层次结构。例如,ConfigureForDOS / ConfigureForUnix / ConfigureForX 问题。
- 当您需要根据对象的类型对对象执行非常不同的操作时。
- 当被访问的类层次结构将经常用 Element 类的新的派生类进行扩展时。
- 当 Element 的派生类的重新编译、重新链接、重新测试或重新分发非常昂贵时。
无环访问者模式的 Java 教程
无环访问者模式的优势和权衡
优势
- 可扩展性:可以轻松添加新操作,而无需更改对象结构。
- 解耦:减少了对象与其操作之间的耦合。
- 没有依赖循环:确保无环依赖关系,提高可维护性并降低复杂性。
权衡
- 复杂性增加:可能由于需要多个访问者接口而引入额外的复杂性。
- 维护开销:修改对象层次结构需要更新所有访问者。