访问者模式

访问者模式(Visitor Pattern)一句话记忆:  
> **“把** **对数据结构的操作** **从** **数据结构本身** **中分离出来,让同一批元素可以接受不同的‘访问者’来执行不同的行为。”**

---

### 🧩 场景类比

想象一个 **动物园**:

- **元素**:狮子、老虎、大象 …(它们是数据结构里的节点)  
- **访问者**:  
  - **饲养员**(喂食)  
  - **兽医**(体检)  
  - **游客**(拍照)

> 动物(元素)不需要知道“谁来干什么”,  
> 每个访问者只需实现“对狮子怎么做、对老虎怎么做”。

---

### 🔍 回到 Java / Lucene

#### 1. 典型 API:`Files.walkFileTree`

```java
Files.walkFileTree(root, new SimpleFileVisitor<Path>() {
    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
        // 对“文件”这个元素的操作
        return FileVisitResult.CONTINUE;
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
        // 对“目录”这个元素的操作
        return FileVisitResult.CONTINUE;
    }
});
```

- **元素**:`Path` 代表的文件或目录  
- **访问者**:`SimpleFileVisitor` 的匿名子类  
- **好处**:新增“压缩访问者”、“统计访问者”时,**无需修改目录/文件类**。

#### 2. 结构图

```
+-------------------+          +------------------+
|   元素(File)      |          |   元素(Dir)      |
+-------------------+          +------------------+
| accept(Visitor)   |          | accept(Visitor)  |
+---------+---------+          +---------+--------+
          |                            |
          |        +-------------------v----------------+
          |        |         访问者接口                   |
          |        | + visit(File) + visit(Dir)         |
          |        +-------------------+----------------+
          |                            |
          |        +-------------------v----------------+
          |        |  具体访问者A:打印路径               |
          |        |  具体访问者B:统计大小               |
          +-------->  具体访问者C:高亮内容               |
```

---

### ✅ 优缺点速记

| 优点 | 缺点 |
|---|---|
| 新增操作只需再写一个访问者,**不改动元素类** | 元素一旦新增类型,**所有访问者都要加新方法** |

---

### 🧩 一句话背下来

 **“元素只负责‘接待’,访问者决定‘做什么’。”**

没有 Visitor 行不行?—— 用“动物园”故事讲透

## 没有 Visitor 行不行?—— 用“动物园”故事讲透

---

### 🐘 **情景 1:没有访问者模式**

你开了一家动物园,动物们自己“包办一切”:

```java
class Elephant {
    void feed()   { System.out.println("大象吃草"); }
    void heal()   { System.out.println("大象体检"); }
    void photo()  { System.out.println("大象拍照"); }
}

class Lion {
    void feed()   { System.out.println("狮子吃肉"); }
    void heal()   { System.out.println("狮子体检"); }
    void photo()  { System.out.println("狮子拍照"); }
}
```

#### 🚩 问题
- **每新增一种操作**(如“称重”),**所有动物类都要改一次** → **类爆炸**。
- **每新增一种动物**(如“长颈鹿”),**所有操作又要复制粘贴一次** → **违反开闭原则**。

---

### 🏗️ **情景 2:引入访问者模式**

把“操作”抽出来,动物只做“接待”:

```java
interface Animal {
    void accept(Visitor v);
}

class Elephant implements Animal {
    public void accept(Visitor v) { v.visit(this); }
}

interface Visitor {
    void visit(Elephant e);
    void visit(Lion l);
}

class FeedVisitor implements Visitor {
    public void visit(Eleph

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值