登录/注册
小张
1699
占位
2
占位
0
浏览量
占位
粉丝
占位
关注
初识设计模式
小张
2023-01-01 11:06:02 2023-01-01
3
0

简介

访问者设计模式(Visitor Design Pattern)的定义是,允许一个或多个操作应用到一组对象上,解耦操作和对象本身。

在使用访问者模式的时候,被访问的元素通常不是单独存在的,它们存储在一个集合中,这个集合称为“对象结构”,访问者通过遍历对象结构实现对其存储的元素进行逐个访问。

访问者模式使用了“双重分派”的调用机制,即元素对象定义一个操作方法支持注入访问者对象,在操作方法内调用访问者的访问方法,并将当前元素对象传入到访问方法中。

具体实现

在这里举一个工作当中的具体例子,在小公司的项目组当中,名义上区分了开发、测试等岗位,但实际上开发人员既要会开发,也有会测试,对于测试人员也是同样的要求,既要会测试,也要会开发。

在这里案例当中,开发人员、测试人员统称为元素,我们在这里先构建一个抽象的元素类。其代码示例如下:

public interface Element {
// 定义一个接受访问者访问的抽象方法
void accept(Visitor visitor);
}

对于开发人员类,根据自己的情况实现这个 accept() 方法,其代码如下:

public class Programmer implements Element {
private String name = "开发人员";
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(Visitor visitor) {
visitor.visitProgrammer(this);
}
}

对于测试人员,根据自己的情况实现这个 accept() 方法,其代码如下:

public class Tester implements Element {
private String name = "测试人员";
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
@Override
public void accept(Visitor visitor) {
visitor.visitTester(this);
}
}

第二步,最重要的就是要定义好一个访问者类,在这里抽象出的访问者接口可以是以项目组为范围,为项目组中的每一个元素定义对应的访问方法。其代码示例如下:

public interface Visitor {
void visitProgrammer(Programmer programmer);
void visitTester(Tester tester);
}

每当出现一个新的操作时,就可以实现访问者接口,注入不同的元素对象以实现不同的操作。

如下是开发人员和测试人员使用开发技能的代码示例:

public class DevelopVisitor implements Visitor {
@Override
public void visitProgrammer(Programmer programmer) {
System.out.println(programmer.getName() + "在开发");
}
@Override
public void visitTester(Tester tester) {
System.out.println(tester.getName() + "在开发");
}
}

如下是开发人员和测试人员使用测试技能的代码示例:

public class TestVisitor implements Visitor {
@Override
public void visitProgrammer(Programmer programmer) {
System.out.println(programmer.getName() + "在测试");
}
@Override
public void visitTester(Tester tester) {
System.out.println(tester.getName() + "在测试");
}
}

总结

优点

访问者模式的主要优点如下:

  • 能够在不修改对象结构中的元素的情况下,为对象结构中的元素添加新的功能,符合开闭原则
  • 将有关元素的行为都封装到一个访问者对象中,每个访问者对象的功能都比较单一,符合单一职责原则

缺点

访问者模式的主要缺点如下:

  • 增加新的元素类需要在每一个访问者类中都增加相应的具体操作,这违背了开闭原则
  • 访问者对象可以访问并调用每一个元素对象的操作,这意味着元素对象有时候会暴露一些内部操作和内部状态,破坏了封装
  • 访问者模式依赖了具体类,而没有依赖抽象类,违反了依赖倒置原则

适用场景

访问者模式的适用场景如下:

  • 对象结构中元素对象的类很少改变,但经常需要在此对象结构上定义新的操作

源码

访问者模式提供一个方便的可维护的方式来操作一组对象,JDK 内置了这样的元素接口和访问者接口。

如下是元素接口 javax.lang.model.element.Element 的部分代码:

public interface Element extends javax.lang.model.AnnotatedConstruct {
<R, P> R accept(ElementVisitor<R, P> v, P p);
}

如下是访问者接口 javax.lang.model.element.ElementVisitor 的部分代码:

public interface ElementVisitor<R, P> {
R visit(Element e, P p);
default R visit(Element e) {
return visit(e, null);
}
}
暂无评论