- 通常访问者模式会结合组合模式一起来用。组合模式对我们的建议是:使用递归而非迭代去操作复杂的数据结构。访问者模式侧重将具体的操作逻辑与复杂数据结构分离出来。把操作逻辑放到访问者里面去。
- 重构一下部门树,将之前的remove()等逻辑抽象为操作访问者的逻辑。
public static class Department { private String name; private List<Department> children = new ArrayList<Department>(); public Department(String name) { super(); this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } public List<Department> getChildren() { return children; } public void setChildren(List<Department> children) { this.children = children; } //这里接客,可以观光 public void accept(Visitor visitor) { visitor.visit(this); } }
- 构造访问者接口,它专门处理对Department这种复杂数据结构的操作。
public interface Visitor { void visit(Department dept); }
- 实现访问者接口,构造删除部门和更新部门两种访问操作。
public static class RemoveVisitor implements Visitor { public void visit(Department dept) { if(dept.getChildren().size() > 0) { for(Department child : dept.getChildren()) { //在这里实现递归遍历 child.accept(this); } } System.out.println("删除部门【" + dept.getName() + "】"); } } public static class UpdateStatusVisitor implements Visitor { private String status; public void visit(Department dept) { if(dept.getChildren().size() > 0) { for(Department child : dept.getChildren()) { //在这里实现递归遍历 child.accept(this); } } System.out.println("将部门【" + dept.getName() + "】的状态修改为:" + status); } public UpdateStatusVisitor(String status) { this.status = status; } }
public static void main(String[] args) { Department leafDept1 = new Department("叶子部门1"); Department leafDept2 = new Department("叶子部门2"); Department leafDept3 = new Department("叶子部门3"); Department subDept1 = new Department("子部门1"); subDept1.getChildren().add(leafDept1); subDept1.getChildren().add(leafDept2); Department subDept2 = new Department("子部门2"); subDept2.getChildren().add(leafDept3); Department parentDept = new Department("父部门"); parentDept.getChildren().add(subDept1); parentDept.getChildren().add(subDept2); Visitor removeVisitor = new RemoveVisitor(); parentDept.accept(removeVisitor); Visitor updateStatusVisitor = new UpdateStatusVisitor("禁用"); parentDept.accept(updateStatusVisitor); }