设计模式-访问者模式

发布时间:2023年12月21日
设计模式专栏


模式介绍

访问者模式是一种行为设计模式,它表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素类的前提下定义作用于这些元素的新操作。

在访问者模式中,一个访问者类实现了访问者接口,可以访问对象结构中的元素。这个接口定义了访问者可以执行的操作。然后,每个元素类都实现了元素接口,这个接口定义了元素可以接受的操作。

访问者模式将数据的操作与数据结构进行分离,使得操作集合可相对自由地演化而不影响系统的数据结构。同时,通过访问者来定义整个对象结构通用的功能,从而提高系统的复用程度。

在这里插入图片描述

模式特点

访问者模式是一种行为设计模式,它允许你在不改变类的前提下增加新的操作。以下是访问者模式的优点和缺点:

  • 优点:
  1. 解耦:访问者模式解耦了数据结构与数据操作,使得操作集合可以独立变化。
  2. 扩展性好:可以通过扩展访问者角色,实现对数据集的不同操作。
  3. 元素具体类型并非单一,访问者均可操作
  4. 各角色职责分离,符合单一职责原则
  • 缺点:
  1. 无法增加元素类型:若系统数据结构易于变化,经常有新的数据对象增加进来,则访问者类必须增加对应元素类型的操作,违背了开闭原则。
  2. 具体元素变得更困难:具体元素增加属性、删除属性等操作会导致对应的访问者类需要进行相应的修改,尤其当有大量访问者类时,修改范围太大。
  3. 违背依赖倒置原则:为了达到“区别对待”,访问者依赖的是具体元素类型,而不是抽象。

在这里插入图片描述

应用场景

访问者模式的应用场景包括:

  • 当一个对象的操作依赖于其元素类的结构时,即需要对一个对象结构中的每一个元素都执行一些操作,并且这些操作依赖于元素的具体类时,应该使用访问者模式。
  • 当需要在不修改现有类的情况下,增加新的操作时,应该使用访问者模式。
  • 当一个操作依赖于一个对象结构中的多个对象时,应该使用访问者模式。
  • 当一个操作需要在多个对象结构之间进行动态切换时,应该使用访问者模式。

访问者模式适用于需要处理的数据结构复杂且经常需要添加新的操作的情况。

在这里插入图片描述

访问者模式与代理模式的区别

访问者模式和代理模式在目的和应用场景上存在一些区别。

访问者模式的主要目的是在处理含有不同类型元素的数据结构时进行优化。它允许你在不改变类的前提下增加新的操作,解耦了数据结构与数据操作,使得操作集合可以独立变化。而代理模式的主要目的是提供一个替身来控制对对象的访问,从而可以在目标对象实现的基础上增强额外的功能操作,扩展目标对象的功能。

在应用场景上,访问者模式适用于数据结构经常变化的情况,因为它可以灵活地添加新的操作。而代理模式则适用于需要控制对对象的访问、增强对象的功能等场景,例如远程对象、创建开销大的对象或需要安全控制的对象。

访问者模式和代理模式都是设计模式中的重要模式,它们在不同的场景下有着各自的应用。

在这里插入图片描述

代码示例

Java实现访问者模式

下面是一个Java实现访问者模式的示例:

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

// 具体元素1
class ConcreteElement1 implements Element {
    private String name;
    
    public ConcreteElement1(String name) {
        this.name = name;
    }
    
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    
    public String getName() {
        return name;
    }
}

// 具体元素2
class ConcreteElement2 implements Element {
    private String name;
    
    public ConcreteElement2(String name) {
        this.name = name;
    }
    
    @Override
    public void accept(Visitor visitor) {
        visitor.visit(this);
    }
    
    public String getName() {
        return name;
    }
}

// 访问者接口
interface Visitor {
    void visit(ConcreteElement1 element);
    void visit(ConcreteElement2 element);
}

// 具体访问者1
class ConcreteVisitor1 implements Visitor {
    @Override
    public void visit(ConcreteElement1 element) {
        System.out.println("访问元素1:" + element.getName());
        // 执行具体操作1...
    }
    
    @Override
    public void visit(ConcreteElement2 element) {
        System.out.println("访问元素2:" + element.getName());
        // 执行具体操作2...
    }
}

// 具体访问者2
class ConcreteVisitor2 implements Visitor {
    @Override
    public void visit(ConcreteElement1 element) {
        System.out.println("访问元素1:" + element.getName());
        // 执行具体操作3...
    }
    
    @Override
    public void visit(ConcreteElement2 element) {
        System.out.println("访问元素2:" + element.getName());
        // 执行具体操作4...
    }
}

// 客户端代码
public class Client {
    public static void main(String[] args) {
        // 创建元素列表和访问者列表
        List<Element> elements = new ArrayList<>();
        elements.add(new ConcreteElement1("元素1"));
        elements.add(new ConcreteElement2("元素2"));
        List<Visitor> visitors = new ArrayList<>();
        visitors.add(new ConcreteVisitor1());
        visitors.add(new ConcreteVisitor2());
        
        // 遍历元素列表,并使用对应的访问者访问每个元素,执行相应的操作。注意:这里为了演示,直接在每个访问者中执行了不同的操作。在实际应用中,你可能需要根据实际需求来定义不同的操作。同时,也可以使用Lambda表达式来简化代码。例如:visitors.forEach(v -> elements.forEach(e -> e.accept(v)));。这样代码会更简洁。

python实现访问者模式

访问者模式是一种行为设计模式,它可以在不改变类的前提下增加新的操作。以下是一个使用Python实现访问者模式的示例:

class Element:
    def accept(self, visitor):
        pass

class ConcreteElement1(Element):
    def accept(self, visitor):
        visitor.visit_concrete_element1(self)

class ConcreteElement2(Element):
    def accept(self, visitor):
        visitor.visit_concrete_element2(self)

class Visitor:
    def visit_concrete_element1(self, element):
        pass
    
    def visit_concrete_element2(self, element):
        pass

class Client:
    def __init__(self):
        self.elements = [ConcreteElement1(), ConcreteElement2()]
        self.visitor = Visitor()
    
    def perform_operation(self):
        for element in self.elements:
            element.accept(self.visitor)
            print("Visited element:", element)
            print("Operation performed on element:", self.visitor.operation)

在这个示例中,我们定义了一个抽象的Element类,它有一个accept方法,用于接受一个Visitor对象。然后我们定义了两个具体的元素类ConcreteElement1ConcreteElement2,它们分别实现了accept方法,用于接受访问者并执行相应的操作。我们还定义了一个Visitor类,它有两个方法,分别用于访问两个具体的元素。最后,我们定义了一个Client类,它包含一个元素列表和一个访问者对象。在perform_operation方法中,我们遍历元素列表,并使用访问者对象访问每个元素,执行相应的操作。

在这里插入图片描述

访问者模式在spring中的应用

在Spring框架中,访问者模式的应用主要体现在对BeanDefinition的访问上。每个Spring中的对象都会被解析成BeanDefinition,然后通过访问者模式,使用Spring的BeanDefinitionVisitor来访问BeanDefinition。

具体来说,访问者模式允许在不改变数据结构的前提下,定义作用于这些元素的新的操作。在Spring中,BeanDefinition就是数据结构中的元素,而BeanDefinitionVisitor就是访问者,用于对这些元素进行操作。

在这里插入图片描述

设计模式-代理模式

设计模式-观察者模式

文章来源:https://blog.csdn.net/zhangzehai2234/article/details/135120145
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。