设计模式 - 访问者模式
访问者模式(Visitor Pattern)允许你在不修改对象结构的情况下,增加新的操作。这就像是你通过一个“访问者”对象来访问一 组元素,执行各种操作。
访问者模式的核心角色:
- 元素(Element):所有需要被访问的类,通常有一个 accept()方法,用来接受访问者的访问。
- 具体元素(ConcreteElement):元素类的具体实现,它实现了 accept()方法,通常会将访问者传递到具体的处理方法。
- 访问者(Visitor):定义所有访问方法,每个访问方法对应一种元素类型。
- 具体访问者(ConcreteVisitor):实现具体操作,如何访问元素并执行相应的动作。
核心思想 🌟
将操作分离出来,封装在一个“访问者”对象中,使得操作可以在不修改元素类的情况下添加到对象结构上。
模式结构(UML 类图)
              +----------------------------+
              |        Visitor             |
              +----------------------------+
              | + visitConcreteElementA()  |
              | + visitConcreteElementB()  |
              +----------------------------+
                            ▲
           +----------------+-----------------+
           |                                  |
+--------------------------+      +--------------------------+
|     ConcreteVisitorA     |      |     ConcreteVisitorB     |
+--------------------------+      +--------------------------+
| + visitConcreteElementA()|      | + visitConcreteElementB()|
+--------------------------+      +--------------------------+
+------------------+  
| Element          |  
+------------------+  
| + accept()       |  
+------------------+  
         ▲
         |
+----------------------+
| ConcreteElementA     |
+----------------------+
| + accept()           |
+----------------------+
示例场景
想象你有一个复杂的对象结构,比如各种不同类型的 Animal(动物)类,你可能希望执行不同的操作,如发出声音。
但你不想在每个类中重复写操作代码。这时候,你就可以使用访问者模式。你可以创建一个“访问者”对象,它知道如何操作这些类,而不需要修改每个类的定义。
Java 实现
// 访问者接口
interface AnimalVisitor {
    void visit(Dog dog);
    void visit(Cat cat);
}
// 动物接口(元素)
interface Animal {
    void accept(AnimalVisitor visitor);
}
// 具体元素
class Dog implements Animal {
    public void accept(AnimalVisitor visitor) {
        visitor.visit(this);
    }
    public void bark() {
        System.out.println("Woof!");
    }
}
class Cat implements Animal {
    public void accept(AnimalVisitor visitor) {
        visitor.visit(this);
    }
    public void meow() {
        System.out.println("Meow!");
    }
}
// 具体访问者
class AnimalSoundVisitor implements AnimalVisitor {
    public void visit(Dog dog) {
        dog.bark();
    }
    public void visit(Cat cat) {
        cat.meow();
    }
}
// 使用
public class Main {
    public static void main(String[] args) {
        Animal dog = new Dog();
        Animal cat = new Cat();
        AnimalVisitor soundVisitor = new AnimalSoundVisitor();
        dog.accept(soundVisitor);  // 输出:Woof!
        cat.accept(soundVisitor);  // 输出:Meow!
    }
}
C++ 实现
#include <iostream>
using namespace std;
// 访问者接口
class AnimalVisitor {
public:
    virtual void visit(class Dog&) = 0;
    virtual void visit(class Cat&) = 0;
    virtual ~AnimalVisitor() = default;
};
// 元素接口
class Animal {
public:
    virtual void accept(AnimalVisitor& visitor) = 0;
    virtual ~Animal() = default;
};
// 具体元素
class Dog : public Animal {
public:
    void accept(AnimalVisitor& visitor) override {
        visitor.visit(*this);
    }
    void bark() {
        cout << "Woof!" << endl;
    }
};
class Cat : public Animal {
public:
    void accept(AnimalVisitor& visitor) override {
        visitor.visit(*this);
    }
    void meow() {
        cout << "Meow!" << endl;
    }
};
// 具体访问者
class AnimalSoundVisitor : public AnimalVisitor {
public:
    void visit(Dog& dog) override {
        dog.bark();
    }
    void visit(Cat& cat) override {
        cat.meow();
    }
};
// 使用
int main() {
    Dog dog;
    Cat cat;
    AnimalSoundVisitor soundVisitor;
    dog.accept(soundVisitor); // 输出:Woof!
    cat.accept(soundVisitor); // 输出:Meow!
    return 0;
}
Python 实现
from abc import ABC, abstractmethod
# 访问者接口
class AnimalVisitor(ABC):
    @abstractmethod
    def visit(self, animal):
        pass
# 元素接口
class Animal(ABC):
    @abstractmethod
    def accept(self, visitor):
        pass
# 具体元素
class Dog(Animal):
    def accept(self, visitor):
        visitor.visit(self)
    def bark(self):
        print("Woof!")
class Cat(Animal):
    def accept(self, visitor):
        visitor.visit(self)
    def meow(self):
        print("Meow!")
# 具体访问者
class AnimalSoundVisitor(AnimalVisitor):
    def visit(self, animal):
        if isinstance(animal, Dog):
            animal.bark()
        elif isinstance(animal, Cat):
            animal.meow()
# 使用
dog = Dog()
cat = Cat()
sound_visitor = AnimalSoundVisitor()
dog.accept(sound_visitor)  # 输出:Woof!
cat.accept(sound_visitor)  # 输出:Meow!
TypeScript 实现
interface Animal {
  accept(visitor: AnimalVisitor): void;
}
interface AnimalVisitor {
  visit(dog: Dog): void;
  visit(cat: Cat): void;
}
class Dog implements Animal {
  accept(visitor: AnimalVisitor): void {
    visitor.visit(this);
  }
  bark() {
    console.log("Woof!");
  }
}
class Cat implements Animal {
  accept(visitor: AnimalVisitor): void {
    visitor.visit(this);
  }
  meow() {
    console.log("Meow!");
  }
}
class AnimalSoundVisitor implements AnimalVisitor {
  visit(dog: Dog): void {
    dog.bark();
  }
  visit(cat: Cat): void {
    cat.meow();
  }
}
// 使用
const dog = new Dog();
const cat = new Cat();
const soundVisitor = new AnimalSoundVisitor();
dog.accept(soundVisitor); // 输出:Woof!
cat.accept(soundVisitor); // 输出:Meow!
小结
| 特性 | 内容 | 
|---|---|
| 模式类型 | 行为型 | 
| 适用场景 | 
 | 
| 优点 | 
 | 
| 缺点 | 
 | 
访问者模式是处理复杂对象结构时非常有用的模式,它使得你可以把操作逻辑和数据结构分离开,遵循了“开放/封闭原则”,非常适合需要增加新操作而不修改已有元素类的场景。