定义:表示一个作用于某对象结构中的各元素的操作,它使得用户可以再不改变各元素的累的前提下定义作用于这些元素的新操作,它是一种对象行为模式。
类图:
说明:抽象访问者Visitor是一个抽象访问者,声明访问者可以访问哪些元素;具体访问者ConcreteVisitor就是指访问者访问到一个类后要做什么事情;抽象元素Element是一个抽象类,生命接受哪一类型的访问者访问;具体元素ConcreteElement会实现accept方法;而结构对象ObjectStructure是一个容纳多个不同类、不同接口的容器(如列表或者无序集合),是使用访问者模式必备的角色。
据《大话设计模式》中说是最复杂也是最难以理解的一种模式。在这里有一句话提出来帮助读者去理解,那就是“一千个读者有一千个哈姆雷特”,这句话有两层含义;①书是一个抽象元素,《哈姆雷特》作为一个具体元素可以接受访问者的“访问”;②读者们“访问”完《哈姆雷特》之后会有自己的见解,这就相当于读者们各自运行了自己的方法一样。
优点:
1.增加新的访问操作很方便。
2.符合单一职责原则:将有关元素对象的访问行为集中到一个访问者对象中,而不是分散在一个个的元素类中,使累的职责更加清晰。
3.让用户能够在不修改现有元素类层次结构的情况下,定义作用于该层次结构的操作。
缺点:
1.增加新的元素类很困难
2.破坏封装
实例场景:购物车,顾客在超市izhong将选择的商品,如苹果,图书等放在购物车中,然后到收银员处付款。在购物车过程中,顾客需要对这些商品进行访问,以便确认这些商品的质量,之后收银员计算价格时也需要访问购物车内顾客所选择的商品,此时,购物车作为一个ObjectStructure(对象结构),用于存储各种类型的商品,而顾客和收银员作为访问这些商品的访问者,他们需要对商品进行检查和计价。不同类型的商品器访问形式也可能不同,如苹果需要过秤之后在计价,而图书不需要。使用访问者模式来设计该购物过程。
实例类图:
实例代码:
//访问者类
public abstract class Visitor {
protected String name;
public String getName() {
return name;
}
public void setName(String newName) {
name = newName;
}
public abstract void visit(Apple apple);
public abstract void visit(Book book);
}
public class Customer extends Visitor {
public void visit(Apple apple) {
// TODO: implement
System.out.println("顾客买了"+apple.getName());
}
public void visit(Book book) {
// TODO: implement
System.out.println("顾客买了"+book.getName());
}
}
public class Saler extends Visitor {
public void visit(Apple apple) {
// TODO: implement
System.out.println("销售员卖了"+apple.getName());
}
public void visit(Book book) {
// TODO: implement
System.out.println("销售员卖了"+book.getName());
}
}
//被访问这类
public interface Product {
void accept(Visitor v);
}
public class Apple implements Product {
private String name = "苹果";
public String getName(){
return name;
}
public void accept(Visitor v) {
// TODO: implement
v.visit(this);
}
public void operatorA() {
// TODO: implement
System.out.println("暂无操作");
}
}
public class Book implements Product {
private String name = "书籍";
public String getName(){
return name;
}
public void accept(Visitor v) {
// TODO: implement
v.visit(this);
}
public void operatorB() {
// TODO: implement
System.out.println("暂无操作");
}
}
//购物车类
public class ShoppingCart {
private List<Product> list = new ArrayList<Product>();
/**
* 接受访问者
*
* @param visitor
*/
public void accept(Visitor visitor) {
// TODO: implement
for (Product p : list) {
p.accept(visitor);
}
}
public void addProduct(Product product) {
// TODO: implement
list.add(product);
}
public void removeProduct(Product product) {
// TODO: implement
list.remove(product);
}
}
//测试客户端:
public class Client {
public static void main(String[] args) {
Visitor customer = new Customer();
Visitor saler = new Saler();
Product apple = new Apple();
Product book = new Book();
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.addProduct(apple);
shoppingCart.addProduct(book);
shoppingCart.accept(customer);
shoppingCart.accept(saler);
}
}
实例代码运行结果: