设计模式的学习已经到了最后阶段,这个模式是GOF中我认为最难理解的一个。GOF中四人有位作者说过:“大多时候你并不需要使用访问者模式,但是当你一旦需要使用了,那么你是真的需要它了”。
什么是访问者模式
来自大话:“表示一个作用于某对象结构中各元素的操作。它使你可以在不改变个元素的类的前提下定义作用于这些元素的新操作”
接下来直接看源码
定义了一个accept方法以访问者对象(Visitor)为参数
public interface Element {
void accept(Visitor visitor);
}
聚合对象(ObjectStructure)
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);
}
}
Element的实现类(顾客)
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);
}
}
}
Element的实现类订单(Order)
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);
}
}
}
Element的实现类商品(Item)
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);
}
}
访问者接口(Element的实现类为参数)实现了visit方法
public interface Visitor {
void visit(Customer customer);
void visit(Order order);
void visit(Item item);
}
访问者的实现类。(GeneralReport)
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
总结
看了一遍代码不知道大家是不是和我一样觉得访问者很复杂。麻烦但是我还是希望大家看到一个点。那就是访问者模式把业务逻辑都放到了Visitor这个对象中。从而我们可以得知,访问者如果我们要加代码或者功能是很容易的。我们只需要增加新的访问者对象就行。
有利就有弊,访问者使用起来比较复杂,如果被访问者的数据结构不确定的情况,使用这个模式的话。那么如果数据结构没有确定的话,要去改变是很麻烦的。因为被访问者增加了,那么访问者就得改。在现实中,不改变数据结构的很少。所有我们用到这个模式的机会便不是那么多。
注意:本文归作者所有,未经作者允许,不得转载