如何深刻理解Java设计模式中的访客模式,相信很多没有经验的人对此无能为力。为此,本文总结了问题产生的原因和解决方法,希望大家可以通过这篇文章来解决这个问题。
一、什么是访问者模式
定义:表示作用于其对象结构中每个元素的操作,这使您能够定义作用于这些元素的新操作,而无需更改每个元素的类。
可以对定义这么理解:有一种操作作用于属于对象结构的某些元素。同时,这个操作是建立在不改变每个元素类的前提下的,在这个前提下定义一个新的操作就是访客模式的本质。
主要解决:稳定数据结构和易失性操作耦合问题。它是将数据结构与作用在结构上的操作解耦,使操作集可以相对自由地演化。
本质:预约访问和实现回叫。它的实现主要是通过预先定义调用路径来定义访问对象上的接受方法和访问对象上的访问方法。然后,当调用真正发生时,使用二次分发技术和预定义的路径将其回调到访问者的特定实现。
二、访问者模式的结构
Visitor抽象访问者接口:它定义了访问每个元素的行为。其参数是可访问的元素。理论上,其方法的数量与元素的数量(元素的实现类的数量)相同。从这一点不难看出,访问者模式要求元素类的数量不能改变(如果元素类的数量频繁变化,就说明访问者模式不适合)。
ConcreteVisitor具体访问者角色:它需要给出访问每个元素类时的具体行为。
Element抽象节点(元素)角色:它定义了一种接受访问者的方法,这意味着每个元素都必须被访问者访问。
ConcreteElement具体节点(element)角色:它提供了接受访问方法的具体实现,这个具体实现通常使用访问者提供的方法来访问element类。
ObjectStructure结构对象角色:这是定义中提到的对象结构。对象结构是一个抽象表达式。具体来说,它可以理解为具有容器属性或复合对象属性的类。它将包含一组元素,这些元素可以被迭代以供访问者访问。
00-1010 (1)对象结构相对稳定,但往往需要在这个对象结构上定义新的操作。
(2)在一个对象结构中,对对象有很多不同的、不相关的操作,需要避免这些操作“污染”这些对象的类,在增加新的操作时不希望修改这些类。
三、访问者模式的使用场景
优点:
1.访问者模式使得添加新的操作访问者变得容易,并且使得添加依赖于复杂对象结构的组件的操作变得容易。只需添加一个新的访问者来定义对象结构上的新操作。相反,如果每个函数分散在多个类中,则在定义新操作时必须修改每个类。
2.来访者专注于相关的操作,分离不相关的操作。相关的行为不是分布在定义对象结构的类中,而是集中在一个访问者中。无关的行为被放在它们各自的访问者子类中。这简化了这些元素的类和这些访问者中定义的算法。所有与其算法相关的数据结构都可以隐藏在访问者中。
缺点:
1.很难添加新的混凝土元素类
访问者模式使得添加新元素的子类变得困难。每次添加新的混凝土元素时,都应该在Vistor中添加一个新的抽象操作,并且应该在每个混凝土访问者类中实现相应的操作。有时,可以在Visitor中提供默认实现,这可以被大多数混凝土Visitor继承,但这与其说是一个规则,不如说是一个例外。
因此,在应用访问者模式时,要考虑的关键问题是系统的哪个部分会频繁变化,是作用于对象结构的算法还是构成结构的每个对象的类。如果总是添加新的混凝土元素类,Vistor类的层次结构将变得难以维护。在这种情况下,直接在构成结构的类中定义这些操作可能更容易。如果元素类层次结构是稳定的,并且您不断添加修改过的算法,那么访问者模式可以帮助您管理这些变化。
2.销毁包裹
该方法假设混凝土元素接口的功能足够强大,访问者可以完成他们的工作。因此,这种模式经常迫使您提供公共操作来访问元素的内部状态,这可能会破坏其封装。
四、访问者模式的优缺点
抽象访问者角色:为每个特定节点准备了一个访问操作。
作。
//这里由于有两个节点,因此,对应就有两个访问操作。 public interface Visitor { /** * 对应于NodeA的访问操作 */ public void visit(NodeA node); /** * 对应于NodeB的访问操作 */ public void visit(NodeB node); }
具体访问者
/** * 具体访问者VisitorA类 */ public class VisitorA implements Visitor { /** * 对应于NodeA的访问操作 */ @Override public void visit(NodeA node) { System.out.println(node.operationA()); } /** * 对应于NodeB的访问操作 */ @Override public void visit(NodeB node) { System.out.println(node.operationB()); } } /** * 具体访问者VisitorB类 */ public class VisitorB implements Visitor { /** * 对应于NodeA的访问操作 */ @Override public void visit(NodeA node) { System.out.println(node.operationA()); } /** * 对应于NodeB的访问操作 */ @Override public void visit(NodeB node) { System.out.println(node.operationB()); } }
抽象节点类
/** * 抽象节点类 */ public abstract class Node { /** * 接受操作 */ public abstract void accept(Visitor visitor); }
具体节点类
/** * 具体节点类NodeA */ public class NodeA extends Node { /** * 接受操作 */ @Override public void accept(Visitor visitor) { visitor.visit(this); } /** * NodeA特有的方法 */ public String operationA() { return "NodeA"; } } /** * 具体节点类NodeB */ public class NodeB extends Node { /** * 接受方法 */ @Override public void accept(Visitor visitor) { visitor.visit(this); } /** * NodeB特有的方法 */ public String operationB() { return "NodeB"; } }
结构对象角色类
/** * 结构对象角色类 * 这个结构对象角色持有一个聚集,并向外界提供add()方法作为对聚集的管理操作。通过调用这个方法,可以动态地增加一个新的节点。 */ public class ObjectStructure { private List<Node> nodes = new ArrayList<Node>(); /** * 执行方法操作 */ public void action(Visitor visitor) { for (Node node : nodes) { node.accept(visitor); } } /** * 添加一个新元素 */ public void add(Node node) { nodes.add(node); } }
客户端代码
public static void main(String[] args) { //创建一个结构对象 ObjectStructure os = new ObjectStructure(); //给结构增加一个节点 os.add(new NodeA()); //给结构增加一个节点 os.add(new NodeB()); //创建一个访问者 Visitor visitor = new VisitorA(); os.action(visitor); }
看完上述内容,你们掌握怎么深入理解Java设计模式中的访问者模式的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注行业资讯频道,感谢各位的阅读!
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/71911.html