1.定义
将作用于某种数据结构中的各元素的操作分离出来封装成独立的类,使其在不改变数据结构的前提下可以添加作用于这些元素的新的操作,为数据结构中的每个元素提供多种访问方式。它将对数据的操作与数据结构进行分离,是行为类模式中最复杂的一种模式。
2.理解
有些集合对象中存在多种不同的元素,且每种元素也存在多种不同的访问者和处理方式。电影或电视剧中的人物角色,不同的观众对他们的评价也不同;还有顾客在商场购物时放在“购物车”中的商品,顾客主要关心所选商品的性价比,而收银员关心的是商品的价格和数量。
3.组成
- 抽象访问者(Visitor)角色:定义一个访问具体元素的接口,为每个具体元素类对应一个访问操作 visit()
,该操作中的参数类型标识了被访问的具体元素。 - 具体访问者(ConcreteVisitor)角色:实现抽象访问者角色中声明的各个访问操作,确定访问者访问一个元素时该做什么。
- 抽象元素(Element)角色:声明一个包含接受操作 accept() 的接口,被接受的访问者对象作为 accept() 方法的参数。
具体元素(ConcreteElement)角色:实现抽象元素角色 - 提供的 accept() 操作,其方法体通常都是 visitor.visit(this)
,另外具体元素中可能还包含本身业务逻辑的相关操作。 - 对象结构(Object Structure)角色:是一个包含元素角色的容器,提供让访问者对象遍历容器中的所有元素的方法,通常由
List、Set、Map 等聚合类实现。
4.示例
电脑城有多种不同类型的电脑(轻薄本,游戏本),顾客有男顾客和女顾客,男顾客和女顾客对不同类型的笔记本有不同的评价。
- 电脑城:对象结构
- 电脑:抽象元素
- 游戏本:具体元素
- 轻薄本:具体元素
- 顾客:抽象访问者
- 男生顾客:具体访问者
- 女生顾客:具体访问者
5.java代码
public class VisiterPattern {
public static void main(String[] args) {
//初始化电脑城
ComputerShop shop = new ComputerShop();
GameComputer gameComputer = new GameComputer();
ThinComputer thinComputer = new ThinComputer();
List<IComputer> computerList = new ArrayList<>();
computerList.add(gameComputer);
computerList.add(thinComputer);
shop.setComputers(computerList);
//初始化顾客
ICustomer c1 = new ManCustomer();
ICustomer c2 = new WomanCustomer();
//电脑城向不同的顾客 介绍产品,得到的评价不同
shop.indroductionComputer(c1);
shop.indroductionComputer(c2);
}
}
@Data
class ComputerShop{
private List<IComputer> computers = new ArrayList<>();
public void indroductionComputer(ICustomer customer){
for (IComputer computer : computers) {
computer.accept(customer);
}
}
}
interface IComputer{
void accept(ICustomer customer);
}
interface ICustomer{
//评价产品
String evaluateProduct(GameComputer gameComputer);
String evaluateProduct(ThinComputer thinComputer);
}
class GameComputer implements IComputer{
@Override
public void accept(ICustomer customer) {
System.out.println(customer.evaluateProduct(this));
}
}
class ThinComputer implements IComputer{
@Override
public void accept(ICustomer customer) {
System.out.println(customer.evaluateProduct(this));
}
}
class ManCustomer implements ICustomer{
@Override
public String evaluateProduct(GameComputer gameComputer) {
return "男顾客评价游戏本:性能强,不错!";
}
@Override
public String evaluateProduct(ThinComputer thinComputer) {
return "男顾客评价轻薄本:性能差,打游戏不行!";
}
}
class WomanCustomer implements ICustomer{
@Override
public String evaluateProduct(GameComputer gameComputer) {
return "女顾客评价游戏本:又厚又丑!";
}
@Override
public String evaluateProduct(ThinComputer thinComputer) {
return "女顾客评价轻薄本:这个好看!";
}
}
6.golang代码
func main() {
//初始化电脑城
shop := new(ComputerShop)
computers := []IComputer{new(GameComputer),new(ThinComputer)}
shop.Computers = computers
//两个顾客
c1 := new(ManCustomer)
c2 := new(WomanCustomer)
//向两个顾客介绍产品
shop.IndroductionComputer(c1)
shop.IndroductionComputer(c2)
}
type ComputerShop struct {
Computers []IComputer
}
func (shop *ComputerShop) IndroductionComputer(customer ICustomer) {
for _,v := range shop.Computers{
v.Accept(customer)
}
}
type IComputer interface {
Accept(customer ICustomer)
}
type GameComputer struct {
}
func (c *GameComputer) Accept(customer ICustomer) {
fmt.Println(customer.EvaluateGameComputer(c))
}
type ThinComputer struct {
}
func (c *ThinComputer) Accept(customer ICustomer) {
fmt.Println(customer.EvaluateThinComputer(c))
}
type ICustomer interface {
//注意的是与java不同的是,golang中不支持重载,因此这里的方法名不同。
EvaluateGameComputer(computer *GameComputer) string
EvaluateThinComputer(computer *ThinComputer) string
}
type ManCustomer struct {
}
func (c *ManCustomer) EvaluateGameComputer(computer *GameComputer) string{
return "男顾客评价游戏本:性能强,不错!"
}
func (c *ManCustomer) EvaluateThinComputer(computer *ThinComputer) string{
return "男顾客评价轻薄本:性能差,打游戏不行!"
}
type WomanCustomer struct {
}
func (c *WomanCustomer) EvaluateGameComputer(computer *GameComputer) string{
return "女顾客评价游戏本:又厚又丑!"
}
func (c *WomanCustomer) EvaluateThinComputer(computer *ThinComputer) string{
return "女顾客评价轻薄本:这个好看!"
}