设计模式- 访问者模式(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等)。通过访问者模式,我们能够为这些不同类型的元素定义新的操作(如统计字符数、图片数),而无需修改元素本身的类。

相关推荐
编程、小哥哥2 小时前
设计模式之组合模式(营销差异化人群发券,决策树引擎搭建场景)
决策树·设计模式·组合模式
hxj..4 小时前
【设计模式】外观模式
java·设计模式·外观模式
吾与谁归in4 小时前
【C#设计模式(10)——装饰器模式(Decorator Pattern)】
设计模式·c#·装饰器模式
无敌岩雀5 小时前
C++设计模式行为模式———命令模式
c++·设计模式·命令模式
In_life 在生活15 小时前
设计模式(四)装饰器模式与命令模式
设计模式
瞎姬霸爱.15 小时前
设计模式-七个基本原则之一-接口隔离原则 + SpringBoot案例
设计模式·接口隔离原则
鬣主任16 小时前
Spring设计模式
java·spring boot·设计模式
程序员小海绵【vincewm】18 小时前
【设计模式】结合Tomcat源码,分析外观模式/门面模式的特性和应用场景
设计模式·tomcat·源码·外观模式·1024程序员节·门面模式
丶白泽18 小时前
重修设计模式-行为型-命令模式
设计模式·命令模式
gjh120821 小时前
设计模式:工厂方法模式和策略模式
设计模式·工厂方法模式·策略模式