目录
一. 前言
二. 实现
三. 优缺点
一. 前言
访问者模式,即在不改变聚合对象内元素的前提下,为聚合对象内每个元素提供多种访问方式,即聚合对象内的每个元素都有多个访问者对象。访问者模式主要解决稳定的数据结构和易变元素的操作之间的耦合问题。
二. 实现
Visitor:访问者,为每一个 ConcreteElement 声明一个 visit 操作。
ConcreteVisitor:具体访问者,存储遍历过程中的累计结果。
ObjectStructure:对象结构,可以是组合结构,或者是一个集合。
public interface Element {void accept(Visitor visitor);
}public class Customer implements Element {private String name;private List<Order> orders = new ArrayList<>();Customer(String name) {this.name = name;}String getName() {return name;}void addOrder(Order order) {orders.add(order);}public void accept(Visitor visitor) {visitor.visit(this);for (Order order : orders) {order.accept(visitor);}}
}public class Order implements Element {private String name;private List<Item> items = new ArrayList();Order(String name) {this.name = name;}Order(String name, String itemName) {this.name = name;this.addItem(new Item(itemName));}String getName() {return name;}void addItem(Item item) {items.add(item);}public void accept(Visitor visitor) {visitor.visit(this);for (Item item : items) {item.accept(visitor);}}
}public class Item implements Element {private String name;Item(String name) {this.name = name;}String getName() {return name;}public void accept(Visitor visitor) {visitor.visit(this);}
}
class CustomerGroup {private List<Customer> customers = new ArrayList<>();void accept(Visitor visitor) {for (Customer customer : customers) {customer.accept(visitor);}}void addCustomer(Customer customer) {customers.add(customer);}
}
public interface Visitor {void visit(Customer customer);void visit(Order order);void visit(Item item);
}
public class GeneralReport implements Visitor {private int customersNo;private int ordersNo;private int itemsNo;public void visit(Customer customer) {System.out.println(customer.getName());customersNo++;}public void visit(Order order) {System.out.println(order.getName());ordersNo++;}public void visit(Item item) {System.out.println(item.getName());itemsNo++;}public void displayResults() {System.out.println("Number of customers: " + customersNo);System.out.println("Number of orders: " + ordersNo);System.out.println("Number of items: " + itemsNo);}
}
public class Client {public static void main(String[] args) {Customer customer1 = new Customer("customer1");customer1.addOrder(new Order("order1", "item1"));customer1.addOrder(new Order("order2", "item1"));customer1.addOrder(new Order("order3", "item1"));Order order = new Order("order_a");order.addItem(new Item("item_a1"));order.addItem(new Item("item_a2"));order.addItem(new Item("item_a3"));Customer customer2 = new Customer("customer2");customer2.addOrder(order);CustomerGroup customers = new CustomerGroup();customers.addCustomer(customer1);customers.addCustomer(customer2);GeneralReport visitor = new GeneralReport();customers.accept(visitor);visitor.displayResults();}
}
customer1
order1
item1
order2
item1
order3
item1
customer2
order_a
item_a1
item_a2
item_a3
Number of customers: 2
Number of orders: 4
Number of items: 6
三. 优缺点
优点
1. 符合单一职责原则,即数据的存储和操作分别由对象结构类和访问者类实现。
2. 优秀的扩展性和灵活性。
缺点
1. 具体元素对访问者公布了其细节,违反了迪米特法则。
2. 具体元素的增加将导致访问者类的修改,违反了开闭原则。
3. 访问者类依赖了具体类而不是抽象,违反了依赖倒置原则。
JDK中的访问者模式
javax.lang.model.element.Element and javax.lang.model.element.ElementVisitor
javax.lang.model.type.TypeMirror and javax.lang.model.type.TypeVisitor