Java设计模式 - 访问者模式
定义
封装一些作用于某种数据结构中的哥元素的操作,它可以在不改变数据结构的前提下定义作用于这些元素的新的操作。
看到其定义,确实感到访问者模式的复杂。砍死简单的访问者模式其实是23种设计模式中最难的一个。简单来说,访问者模式就是一种将数据操作与数据结构分离的设计模式。
大多数情况下,我们基本上用不到访问者模式,但是一旦需要用上它,会带来意想不到的效果。
示例
首先,定义一个抽象访问者:
public interface IVisitor {
void visit(Manager manager);
void visit(CommonStaff staff);
}
定义具体的访问者,用于访问被访问者的年龄、姓名:
public class AgeVisitor implements IVisitor {
@Override
public void visit(Manager manager) {
System.out.println("Manager 的年龄: " + manager.getAge());
}
@Override
public void visit(CommonStaff staff) {
System.out.println("CommonStaff 的年龄: " + staff.getAge());
}
}
public class NameVisitor implements IVisitor {
@Override
public void visit(Manager manager) {
System.out.println("Manager 的姓名: " + manager.getName());
}
@Override
public void visit(CommonStaff staff) {
System.out.println("Manager 的姓名: " + staff.getName());
}
}
定义一个抽象访问者员工类型的接口:
public interface Staff {
void accept(IVisitor visitor);
}
员工分为普通员工和管理层:
public class CommonStaff implements Staff {
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
public int getAge() {
return 22;
}
public String getName() {
return "ddd";
}
}
public class Manager implements Staff {
@Override
public void accept(IVisitor visitor) {
visitor.visit(this);
}
public int getAge() {
return 22;
}
public String getName() {
return "ddd";
}
}
最终实现:
public class Lists {
private List<IVisitor> list = new ArrayList<>();
public void add(IVisitor staff) {
list.add(staff);
}
public void visit(Staff staff) {
for (int i = 0; i < list.size(); i++) {
staff.accept(list.get(i));
}
}
}
public class Client {
public static void main(String[] args) {
CommonStaff cs = new CommonStaff();
Manager m = new Manager();
IVisitor ageVisitor = new AgeVisitor();
IVisitor nameVisitor = new NameVisitor();
Lists lists = new Lists();
lists.add(ageVisitor);
// lists.add(nameVisitor);
lists.visit(cs);
lists.visit(m);
}
}
到此为止,访问者模式的结构已经清晰地通过代码展示出来了。对于访问者模式来说,如果不是为业务需求而生,就没必要使用访问者模式,虽然访问者模式有着优秀的对数据结构新的扩展操作,但是同时也有着明显的缺点。
访问者模式的优缺点
优点
1.
访问者和被访问者各司其职,角色单一,符合单一职责原则。
2.
优秀的访问者扩展性。上面的代码可通过增加一个访问者子类,轻易实现扩展。
缺点
1.
被访问者的内部细节对访问者公布,违反了迪米特原则。
2.
访问者依赖的是具体被访问者,而非抽象被访问者,因其需要对具体被访问者做不同操作,违反了依赖倒置原则。
3.
具体元素的变更扩展较困难。上面的示例中,如果在抽象访问者中新增一个 sex 属性,那么访问者势必要做出修改,如果有多个访问者,这种变更就会变得复杂。
访问者模式的应用场景
1.
被访问者内部结构稳定,元素简单不易变化,但需要对其进行结构上的新操作。
2.
业务规则要求遍历多个不同的对象。与迭代器模式的不同点是,迭代器模式访问的是相同基类或接口的对象,而访问者模式面对的是不同类型的对象(也就是说,上面示例中的员工类可以不实现相同的基类 Staff)。其实,访问者模式是迭代器模式的一种特殊扩展。
本文由
Fynn_ 原创,未经许可,不得转载!