设计模式- 访问者模式(Visitor Pattern)结构|原理|优缺点|场景|示例

设计模式(分类) 设计模式(六大原则)

创建型(5种) 工厂方法 抽象工厂模式 单例模式 建造者模式 原型模式

结构型(7种) 适配器模式 装饰器模式 代理模式 ​​​​​​外观模式 桥接模式 组合模式 享元模式

行为型(11种) 策略模式 模板方法模式 观察者模式 迭代器模式 责任链模式 命令模式 备忘录模式 状态模式 访问者模式 中介者模式


访问者模式(Visitor Pattern)是一种行为设计模式,它表示一个作用于某对象结构中的各个元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。访问者模式适用于需要对一个对象结构中的对象进行很多不同类型的运算,而且施加运算的对象又不希望知道这些运算的具体实现的情况。

结构: 访问者模式的主要参与者有:

  1. Visitor(访问者):声明一个访问操作接口,该接口中的每个操作元素对应一个需要访问的对象类的元素。具体访问者则实现了这些操作。
  2. Element(元素):定义一个接受访问者的方法,一般称为accept(),它以一个访问者作为参数。
  3. ConcreteElement(具体元素):实现了Element中的accept()方法,通常会调用访问者的访问方法来完成对一个元素的操作。
  4. ObjectStructure(对象结构):能够枚举它的元素,提供一个接口让访问者可以访问它的元素。

原理:

访问者模式通过双分派机制实现。首先,客户端代码将 ConcreteElement 对象传递给访问者对象;然后,访问者对象根据 ConcreteElement 的类型来决定调用哪个具体的操作方法。这样,增加新的元素类型或新的访问操作都很方便,只需增加新的元素类和新的访问者类即可,原有的代码无需修改。

优缺点:

优点:

  • 扩展性好:增加新的操作变得容易,只需要增加新的访问者类即可,符合开闭原则。
  • 封装性好:将数据结构和操作分离,使得操作集合可独立变化。

缺点:

  • 违反了单一职责原则,将数据结构和算法耦合到了一起。
  • 对象结构变化困难:若要增加新的元素类,需要修改访问者接口及所有具体访问者类,违反了开闭原则。
  • 实现较为复杂,不易理解。

应用场景:

  • 需要对对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作"污染"这些对象的类。
  • 当需要对一个组合结构中的对象进行很多不同类型的操作,而操作算法又彼此独立时。

代码示例(以Java为例)

java 复制代码
// 访问者接口
interface Visitor {
    void visit(TextElement element);
    void visit(ImageElement element);
    void visit(TableElement element);
}

// 具体访问者:统计字符数
class CharacterCounter implements Visitor {
    int count = 0;
    @Override
    public void visit(TextElement element) {
        count += element.getText().length();
    }
    // 图片和表格访问不做处理
    @Override
    public void visit(ImageElement element) {}
    @Override
    public void visit(TableElement element) {}
    // 获取统计结果
    public int getCount() { return count; }
}

// 具体访问者:统计图片数量
class ImageCounter implements Visitor {
    int count = 0;
    @Override
    public void visit(TextElement element) {}
    @Override
    public void visit(ImageElement element) { count++; }
    @Override
    public void visit(TableElement element) {}
    // 获取统计结果
    public int getCount() { return count; }
}

// 元素接口
interface Element {
    void accept(Visitor visitor);
}

// 具体元素:文本
class TextElement implements Element {
    private String text;
    public TextElement(String text) { this.text = text; }
    public String getText() { return text; }
    @Override
    public void accept(Visitor visitor) { visitor.visit(this); }
}

// 其他具体元素:图片、表格的定义省略...

// 对象结构:文档
class Document {
    private List<Element> elements;
    public Document() { elements = new ArrayList<>(); }
    public void add(Element element) { elements.add(element); }
    public void print(Visitor visitor) {
        for (Element e : elements) {
            e.accept(visitor);
        }
    }
}

// 示例使用
public class VisitorPatternDemo {
    public static void main(String[] args) {
        Document doc = new Document();
        doc.add(new TextElement("Hello, World!"));
        doc.add(new ImageElement());
        doc.add(new TableElement());

        Visitor counter1 = new CharacterCounter();
        doc.print(counter1);
        System.out.println("Total characters: " + counter1.getCount());

        Visitor counter2 = new ImageCounter();
        doc.print(counter2);
        System.out.println("Total images: " + counter2.getCount());
    }
}

在这个例子中,Document类代表对象结构,它包含不同类型的Element(如TextElementImageElementTableElement等)。通过访问者模式,我们能够为这些不同类型的元素定义新的操作(如统计字符数、图片数),而无需修改元素本身的类。

相关推荐
三翼鸟数字化技术团队1 小时前
提升开发思维的设计模式(上)
前端·javascript·设计模式
坚持学习永不言弃1 小时前
创建型-原型模式
设计模式
哆啦A梦的口袋呀12 小时前
基于Python学习《Head First设计模式》第十章 状态模式
学习·设计模式
电子科技圈17 小时前
IAR开发平台升级Arm和RISC-V开发工具链,加速现代嵌入式系统开发
arm开发·嵌入式硬件·设计模式·性能优化·软件工程·代码规范·risc-v
昕冉18 小时前
利用 Axrue9 中继器实现表格数据的查询
设计模式·设计
摘星编程1 天前
建造者模式深度解析与实战应用
设计模式·建造者模式·代码重构·对象构建·java实战
周某某~1 天前
六.原型模式
java·设计模式·原型模式
周某某~1 天前
五.建造者模式
java·设计模式·建造者模式
qqxhb2 天前
零基础设计模式——行为型模式 - 命令模式
java·设计模式·go·命令模式
SAP-nkGavin2 天前
ABAP设计模式之---“童子军法则(The Boy Scout Rule)”
设计模式·sap·abap