行为型模式(8)《访问者模式》

访问者模式

该模式的主要目的是将数据结构与数据操作分离,避免在对一个对象结构中的对象进行很多不同的并且不相关的操作时,这些操作"污染"这些对象的类。使用访问者模式将这些封装到类中。

比如现在我们很多人都喜欢网上购物,一般流程都是“浏览商品信息—>付款—>收到商品后评价”。如果将整个购物过程看成是个整体,则这个整体可以看成由上面三部分组成。对于每个不同的小部分,顾客(也就是模式中的访问者)的操作也不同。

模式结构

访问者模式包含以下主要角色:

  • 抽象访问者角色(Visitor):定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit() ,该操作中的参数类型标识了被访问的具体元素。
  • 具体访问者角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
  • 抽象元素角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
  • 具体元素角色:实现抽象元素角色提供的 accept() 操作,其方法体通常都是 visitor.visit(this) ,另外具体元素中可能还包含本身业务逻辑的相关操作。
  • 对象结构角色:是一个包含具体元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由 List、Set、Map 等聚合类实现。
模式结构图

行为型模式(8)《访问者模式》_第1张图片

模式的java实现

以顾客购物为例

抽象访问者接口:

public interface Visitor {
	public void visit(BrowseProduct section);

	public void visit(Pay section);

	public void visit(Reviews section);
}

抽象元素接口,无论浏览商品还是付款或者评价都属于购物这个抽象概念:

public interface Shopping {
	public void accept(Visitor visitor);
}

三个具体元素类,也就是三个不同的购物过程:

// 浏览商品
public class BrowseProduct implements Shopping {
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public String operation() {
		// 这里可以添加详细的浏览过程
		return "已获取商品信息";
	}
}
// 付款
public class Pay implements Shopping {
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public String operation() {
		return "付款成功";
	}
}
// 商品评价
public class Reviews implements Shopping {
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public String operation() {
		return "完成评价";
	}
}

具体访问者,也就是顾客:

public class Customer implements Visitor {
	@Override
	public void visit(BrowseProduct section) {
		System.out.println("浏览商品信息——>" + section.operation());
	}

	@Override
	public void visit(Pay section) {
		System.out.println("准备付款——>" + section.operation());
	}

	@Override
	public void visit(Reviews section) {
		System.out.println("收货后评价——>" + section.operation());
	}
}

对象结构类,将购物过程的所有具体部分聚合在一起:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ShoppingStructure {
	private List<Shopping> list = new ArrayList<>();

	public void accept(Visitor visitor) {
		Iterator<Shopping> it = list.iterator();
		while (it.hasNext()) {
			((Shopping) it.next()).accept(visitor);
		}
	}

	public void add(Shopping section) {
		list.add(section);
	}

	public void remove(Shopping section) {
		list.remove(section);
	}
}

最后就是外部类中创建访问者模拟购物的不同操作:

public class VisitorPattern {
	public static void main(String[] args) {
		// 创建购物过程
		ShoppingStructure structure = new ShoppingStructure();
		structure.add(new BrowseProduct());
		structure.add(new Pay());
		structure.add(new Reviews());

		System.out.println("顾客开始购物...");
		Visitor customer = new Customer();
		structure.accept(customer);
	}
}

上面只提供了一个访问者类型,如果需要增加不同类型的访问者,比如店铺店主,那么访问者类型不同时对各部分的具体操作可能也不一样。比如付款环节顾客支付,店主查看顾客是否已付款。这时候就需要再次实现下 Visitor 接口创建个店主类,在付款部分将具体操作 operation() 方法以不同参数形式多次实现,参数为不同的访问者类型。

具体修改如下:

修改三个具体购物过程中的 operation() 方法:

public class BrowseProduct implements Shopping {
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public String operation(Customer customer) {
		return "顾客浏览商品信息";
	}

	public String operation(Boss boss) {
		return "店主浏览商品信息";
	}
}
public class Pay implements Shopping {
	@Override
	public void accept(Visitor visitor) {
		visitor.visit(this);
	}

	public String operation(Customer customer) {
		return "顾客付款";
	}

	public String operation(Boss boss) {
		return "店主查看顾客是否付款";
	}
}
public class Customer implements Visitor {
	@Override
	public void visit(BrowseProduct section) {
		System.out.println("浏览商品环节——>" + section.operation(this));
	}

	@Override
	public void visit(Pay section) {
		System.out.println("付款环节——>" + section.operation(this));
	}

	@Override
	public void visit(Reviews section) {
		System.out.println("评价环节——>" + section.operation(this));
	}
}

原顾客类中 operation() 方法添加参数:

public class Customer implements Visitor {
	@Override
	public void visit(BrowseProduct section) {
		System.out.println("浏览商品环节——>" + section.operation(this));
	}

	@Override
	public void visit(Pay section) {
		System.out.println("付款环节——>" + section.operation(this));
	}

	@Override
	public void visit(Reviews section) {
		System.out.println("评价环节——>" + section.operation(this));
	}
}

增加访问者类型:

public class Boss implements Visitor {
	@Override
	public void visit(BrowseProduct section) {
		System.out.println("浏览商品环节——>" + section.operation(this));
	}

	@Override
	public void visit(Pay section) {
		System.out.println("付款环节——>" + section.operation(this));
	}

	@Override
	public void visit(Reviews section) {
		System.out.println("评价环节——>" + section.operation(this));
	}
}

其它不变。

你可能感兴趣的:(设计模式)