博主介绍: ✌博主从事应用安全和大数据领域,有8年研发经验,5年面试官经验,Java技术专家✌
Java知识图谱点击链接:体系化学习Java(Java面试专题)
💕💕 感兴趣的同学可以收藏关注下 ,不然下次找不到哟💕💕
1、什么是访问者模式
访问者模式是一种行为型设计模式,它允许在不修改现有对象结构的情况下,定义新的操作或算法。该模式将操作封装在一个访问者对象中,然后通过在被访问的对象上调用接受访问者的方法来实现对被访问对象的操作。
访问者模式的核心思想是将数据结构与数据操作分离。被访问的对象(数据结构)提供接受访问者的方法,而访问者对象则提供具体的操作逻辑。通过访问者模式,我们可以在不改变被访问对象的结构的情况下,增加新的操作或算法。
2、访问者模式的优缺点
访问者模式的优点:
增加新的操作或算法:访问者模式允许在不修改被访问对象的结构的情况下,增加新的操作或算法。通过定义新的具体访问者,可以轻松地在现有对象结构上添加新的操作逻辑。
分离数据结构和操作:访问者模式将数据结构与操作分离,使得数据结构的变化不会影响到操作的定义。这样可以提高系统的灵活性和可扩展性。
增加新的元素类型相对容易:如果需要增加新的元素类型,只需要在访问者接口和具体访问者中添加对应的访问方法即可,不需要修改现有的代码。
访问者模式的缺点:
增加新的元素类型困难:相比于增加新的操作或算法,增加新的元素类型会比较困难。因为需要修改抽象访问者和具体访问者的接口,这可能会导致现有的访问者实现需要进行修改。
增加系统复杂性:访问者模式引入了访问者对象和被访问对象之间的依赖关系,增加了系统的复杂性。同时,访问者模式也会导致对象结构中的元素增加,增加了系统的复杂性和理解难度。
违反了封装原则:访问者模式将操作逻辑分散到具体访问者中,可能会破坏被访问对象的封装性,使得被访问对象暴露了自身的内部细节。这可能会导致访问者对被访问对象的依赖性增加,增加系统的耦合性。
3、访问者模式的应用场景
访问者模式适用于以下场景:
对象结构稳定,但需要在不同的访问者之间进行变化:当对象结构相对稳定,但需要根据不同的访问者进行不同的操作时,可以使用访问者模式。例如,一个电商平台的订单管理系统中,订单对象结构相对稳定,但可能需要根据不同的访问者进行订单的统计、打印、导出等不同操作。
需要对对象结构进行复杂的操作或算法:当需要对对象结构进行复杂的操作或算法时,可以使用访问者模式。访问者模式将操作逻辑封装在具体访问者中,可以避免在被访问对象中增加复杂的操作逻辑,使得代码更加清晰和可维护。
对象结构中的元素类型经常变化:当对象结构中的元素类型经常变化,但需要保持稳定的操作逻辑时,可以使用访问者模式。通过定义抽象访问者和具体访问者,可以灵活地增加新的元素类型,并在具体访问者中定义对应的操作逻辑。
对象结构中的元素之间存在复杂的关联关系:当对象结构中的元素之间存在复杂的关联关系,并且需要对这些关联关系进行操作时,可以使用访问者模式。访问者模式可以通过访问者对象在访问过程中获取到对象结构中的其他元素,从而实现对元素之间关联关系的操作。
总而言之,访问者模式适用于对象结构相对稳定,但需要对其进行复杂操作或算法,并且在不同的访问者之间可能需要变化的场景。
4、访问者模式的结构
访问者模式的结构包括以下几个角色:
访问者(Visitor):定义了对每个具体元素的访问操作,可以通过访问者接口访问不同类型的具体元素。访问者模式中通常会定义多个不同的访问者,每个访问者负责不同的操作逻辑。
具体访问者(Concrete Visitor):实现了访问者接口,具体定义了对每个具体元素的访问操作。每个具体访问者对应一种具体的操作逻辑。
元素(Element):定义了一个接受访问者的接口,可以接受访问者对自身进行操作。元素可以是单个对象,也可以是对象的集合。
具体元素(Concrete Element):实现了元素接口,具体定义了接受访问者的操作。每个具体元素对应一种具体的对象类型。
对象结构(Object Structure):包含了一组元素对象,提供了遍历元素的方法。对象结构可以是一个集合、列表、树等不同的数据结构
5、访问者模式的原理
访问者模式的基本流程如下:
定义元素接口,并在具体元素中实现接口方法,用于接受访问者的访问操作。
定义访问者接口,并在具体访问者中实现接口方法,用于对具体元素进行访问操作。
在对象结构中添加元素对象,并提供遍历元素的方法。
客户端根据需求创建具体访问者对象,并调用对象结构的遍历方法,将具体访问者传入元素对象中进行访问操作。
通过访问者模式,可以将数据结构与操作分离,实现对数据结构的复杂操作和算法的灵活扩展。
6、访问者模式的代码案例
以下是一个使用访问者模式的简单代码案例:
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 接口
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:31
*/
public interface Element {
void accept(Visitor visitor);
}
具体元素A
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 具体元素A
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:31
*/
public class ConcreteElementA implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementA(this);
}
public void operationA() {
System.out.println("具体元素A的操作");
}
}
具体元素B
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 具体元素B
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:32
*/
public class ConcreteElementB implements Element {
@Override
public void accept(Visitor visitor) {
visitor.visitConcreteElementB(this);
}
public void operationB() {
System.out.println("具体元素B的操作");
}
}
访问者接口
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 访问者接口
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:32
*/
public interface Visitor {
void visitConcreteElementA(ConcreteElementA elementA);
void visitConcreteElementB(ConcreteElementB elementB);
}
具体访问者
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 具体访问者
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:32
*/
public class ConcreteVisitor implements Visitor {
@Override
public void visitConcreteElementA(ConcreteElementA elementA) {
System.out.println("访问者对具体元素A进行操作");
elementA.operationA();
}
@Override
public void visitConcreteElementB(ConcreteElementB elementB) {
System.out.println("访问者对具体元素B进行操作");
elementB.operationB();
}
}
对象结构
package com.pany.camp.design.principle.visitor;
import java.util.ArrayList;
import java.util.List;
/**
*
* @description: 对象结构
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:33
*/
public class ObjectStructure {
private List<Element> elements = new ArrayList<>();
public void addElement(Element element) {
elements.add(element);
}
public void removeElement(Element element) {
elements.remove(element);
}
public void accept(Visitor visitor) {
for (Element element : elements) {
element.accept(visitor);
}
}
}
客户端代码
package com.pany.camp.design.principle.visitor;
/**
*
* @description: 客户端代码
* @copyright: @Copyright (c) 2022
* @company: Aiocloud
* @author: pany
* @version: 1.0.0
* @createTime: 2023-06-28 20:33
*/
public class Client {
public static void main(String[] args) {
ObjectStructure objectStructure = new ObjectStructure();
objectStructure.addElement(new ConcreteElementA());
objectStructure.addElement(new ConcreteElementB());
Visitor visitor = new ConcreteVisitor();
objectStructure.accept(visitor);
}
}
我们定义了元素接口(Element)和具体元素类(ConcreteElementA和ConcreteElementB),访问者接口(Visitor)和具体访问者类(ConcreteVisitor),以及对象结构类(ObjectStructure)。在客户端代码中,我们创建了具体元素对象并添加到对象结构中,然后创建具体访问者对象,并调用对象结构的accept方法传入访问者对象进行访问操作。输出结果会根据具体访问者的操作逻辑而有所不同。
输出结果如下:
访问者对具体元素A进行操作
具体元素A的操作
访问者对具体元素B进行操作
具体元素B的操作
Process finished with exit code 0
💕💕 本文由激流原创,原创不易,感谢支持
💕💕喜欢的话记得点赞收藏啊