目的:允许将新功能添加到现有的类层次结构中,而不会影响这些层次结构,也不会有四人帮访客模式中那样循环依赖的问题。
类图:
使用场景:
需要在现有层次结构中添加新功能而无需更改或影响该层次结构时。
当某些功能在层次结构上运行,但不属于层次结构本身时。 例如 ConfigureForDOS / ConfigureForUnix / ConfigureForX问题。
当您需要根据对象的类型对对象执行非常不同的操作时。
当访问的类层次结构将经常使用元素类的新派生进行扩展时。
当重新编译,重新链接,重新测试或重新分发派生元素非常昂贵时。
代码示例:
1.创建解调器访问者接口(所有访问者的基类)和解调器抽象类(接口也可以)
public interface ModemVisitor {
/**
ModemVisitor接口不包含任何访问方法,因此它不依赖于访问的层次结构。
每个派生的访问方法都在其自己的访问者界面中声明
*/
}
public abstract class Modem {
public abstract void accept(ModemVisitor modemVisitor);
}
2.定义派生接口和类
@Slf4j
@Data
public class Zoom extends Modem {
@Override
public void accept(ModemVisitor modemVisitor) {
if (modemVisitor instanceof ZoomVisitor){
((ZoomVisitor) modemVisitor).visit(this);
}else{
log.info("Only ZoomVisitor is allowed to visit Zoom modem");
}
}
}
public interface ZoomVisitor extends ModemVisitor{
void visit(Zoom zoom);
}
@Slf4j
@Data
public class Hayes extends Modem {
@Override
public void accept(ModemVisitor modemVisitor) {
if (modemVisitor instanceof HayesVisitor){
((HayesVisitor) modemVisitor).visit(this);
}else{
log.info("Only HayesVisitor is allowed to visit Hayes modem");
}
}
}
public interface HayesVisitor extends ModemVisitor {
void visit(Hayes hayes);
}
3.定义拓展接口
public interface AllModemVisitor extends HayesVisitor,ZoomVisitor{
}
4.拓展类实现(可选择性的实现)
@Slf4j
public class ConfigureForDosVisitor implements AllModemVisitor {
@Override
public void visit(Hayes hayes) {
log.info(hayes+" used with configurator");
}
@Override
public void visit(Zoom zoom) {
log.info(zoom+" used with configurator");
}
}
@Slf4j
public class ConfigureForUnixVisitor implements ZoomVisitor {
@Override
public void visit(Zoom zoom) {
log.info(zoom+" used with unix configurator.");
}
}
输出:
Hayes() used with configurator
Zoom() used with unix configurator.
Only HayesVisitor is allowed to visit Hayes modem
Zoom() used with configurator
参考:https://java-design-patterns.com/