聊聊设计模式——访问者模式

目录

访问者模式:行为型设计模式

优点

缺点

结构说明

工作流程

代码练习

应用场景

本质

涉及的设计原则

相关设计模式

开源框架中的应用


访问者模式:行为型设计模式

        表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变元素的类的前提下定义作用于这些元素的新操作。

聊聊设计模式——访问者模式_第1张图片

优点

  1. 分离关注点:访问者模式将数据结构和操作分离,使得每个类专注于自己的职责,提高了代码的可维护性和可扩展性。

  2. 增加新操作:可以通过添加新的具体访问者类,来增加新的操作,而不需要修改现有元素或数据结构。

  3. 易于扩展:访问者模式支持在不同的元素上应用不同的操作,非常灵活,易于扩展。

缺点

  1. 增加新元素:如果需要增加新的元素类型,需要修改所有的具体访问者类,可能会引起代码的修改。

  2. 违反封装原则:访问者模式可能会导致元素暴露一些不必要的细节给具体访问者,违反了封装原则。

结构说明

  1. 访问者接口(Visitor Interface):定义了访问数据结构中各种元素的方法,每个方法对应一种元素类型。

  2. 具体访问者(Concrete Visitor):实现了访问者接口,负责实现具体的操作逻辑,即如何处理各种元素。

  3. 元素接口(Element Interface):定义了数据结构中的元素的接口,通常包括 accept 方法,用于接受访问者的访问。

  4. 具体元素(Concrete Element):实现了元素接口,提供了 accept 方法的具体实现,用于接受访问者的访问。

  5. 数据结构(Object Structure):包含了多个元素,提供了方法用于让访问者遍历访问元素。

工作流程

  1. 访问者对象通过元素接口中的 accept 方法访问数据结构中的元素。

  2. 具体元素的 accept 方法会将访问者对象传递给访问者,让访问者处理该元素。

  3. 具体访问者根据元素的类型执行相应的操作。

代码练习

        访问者模式是设计模式中最难理解的几个之一。因为它难理解、难实现,应用它会导致代码的可读性、可维护性变差,所以,访问者模式在实际的软件开发中很少被用到,在没有特别必要的情况下,建议你不要使用访问者模式。

需要一个稳定的数据结构(素体的手办模型,分为上半身和下半身),对结构中元素有多种不同类型的操作(上半身可以穿短袖、羽绒服和卫衣;下半身可以是短裤、牛仔裤和休闲裤)。

1.创建访问者接口Visitor,定义了访问数据结构中各元素(手办模型的上半身和下半身)的方法。

public interface Visitor {
    void visitUpperBody(UpperBody upperBody);
    void visitLowerBody(LowerBody lowerBody);
}

2.创建元素接口Element,包含一个accept()方法,用于接受Visitor访问。

public interface Element {
    void accept(Visitor visitor);
}

3.创建具体元素,手办模型的上半身和下半身。

public class UpperBody implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitUpperBody(this);
    }
}
public class LowerBody implements Element {
    @Override
    public void accept(Visitor visitor) {
        visitor.visitLowerBody(this);
    }
}

4.创建具体访问者,主要负责处理各种元素。SpringVisitor负责给手办穿春装,WinterVisitor负责穿冬装,当然也可以定义上身穿羽绒服,下身穿短裤的犀利哥装扮,新增一个Visitor实现类即可。

public class SpringVisitor implements Visitor{
    @Override
    public void visitUpperBody(UpperBody upperBody) {
        System.out.println("春天上身穿长袖...");
    }
​
    @Override
    public void visitLowerBody(LowerBody lowerBody) {
        System.out.println("春天下身穿休闲裤...");
    }
}
public class WinterVisitor implements Visitor{
    @Override
    public void visitUpperBody(UpperBody upperBody) {
        System.out.println("冬天上身穿羽绒服...");
    }
​
    @Override
    public void visitLowerBody(LowerBody lowerBody) {
        System.out.println("冬天下身穿棉裤...");
    }
}

5.创建数据结构对象—手办模型GarageKit。

// 数据结构对象 - 手办模型
public class GarageKit {
    private List elements = new ArrayList<>();
​
    public void addElement(Element element){
        this.elements.add(element);
    }
    public void removeElement(Element element){
        this.elements.remove(element);
    }
    public void handleVisitor(Visitor visitor){
        for (Element element : elements) {
            element.accept(visitor);
        }
    }
}

6.客户端创建数据结构对象,添加元素和访问者。

public class Client {
    public static void main(String[] args) {
        GarageKit garageKit = new GarageKit();
        garageKit.addElement(new UpperBody());
        garageKit.addElement(new LowerBody());
​
        Visitor springVisitor = new SpringVisitor();
        garageKit.handleVisitor(springVisitor);
        Visitor winterVisitor = new WinterVisitor();
        garageKit.handleVisitor(winterVisitor);
    }
}

应用场景

  1. 当数据结构包含多种不同类型的元素,且需要对这些元素执行不同的操作时,可以考虑使用访问者模式。

  2. 当数据结构的稳定性较高,很少变化,但需要添加新的操作时,访问者模式非常有用,因为它将变化的操作从数据结构中分离出来。

本质

        访问者模式的本质是在不修改数据结构的前提下,定义新的操作或算法。

涉及设计原则

  1. 开闭原则(Open-Closed Principle):访问者模式遵循开闭原则,因为可以通过添加新的具体访问者类来扩展系统,而不需要修改数据结构。

相关设计模式

  • 访问者模式通常与组合模式(Composite Pattern)和迭代器模式(Iterator Pattern)结合使用,以遍历和操作复杂的对象结构。

应用示例

  1. 编译器设计:编译器可以使用访问者模式来遍历语法树,并执行不同的操作,如语法分析、代码生成等。

  2. AST(抽象语法树)处理:在编程语言处理器、解析器和编译器中,访问者模式用于遍历和操作AST中的节点。

  3. 数据库查询优化器:数据库查询优化器可以使用访问者模式来遍历查询计划,并执行优化操作。

  4. 开源框架中的应用:许多开源框架和库,如Hibernate的查询语言HQL、Spring的AOP框架等。

你可能感兴趣的:(设计模式,设计模式,访问者模式)