网站建设无广告语,用ps做网站切片,确定网站文案,涿州网站建设涿州#x1f448;️上一篇:备忘录模式 | 下一篇:状态模式#x1f449;️ 设计模式-专栏#x1f448;️ 文章目录 访问者模式定义英文原话直译如何理解呢#xff1f; 访问者模式的角色类图代码示例 访问者模式的应用优点缺点使用场景 示例解析:博物馆的导览员代码示例 访问… ️上一篇:备忘录模式 | 下一篇:状态模式️ 设计模式-专栏️ 文章目录 访问者模式定义英文原话直译如何理解呢 访问者模式的角色类图代码示例 访问者模式的应用优点缺点使用场景 示例解析:博物馆的导览员代码示例 访问者模式
访问者模式Visitor Pattern就像一位多才多艺的导游能够根据不同的景点数据结构中的元素提供个性化的解说服务操作而无需改变景点的本质。
定义
英文原话
The Visitor pattern is a behavioral design pattern that allows you to add new operations to objects without changing their classes. A visitor is a class with methods that correspond to the classes of an object structure it visits. A client uses the visitor to perform the operations on the elements of the object structure.
直译
访问者模式是一种行为设计模式它允许我们在不改变对象类的情况下为对象添加新的操作。访问者是一个类它包含的方法对应于它所访问的对象结构中的类。客户端使用访问者来对对象结构的元素执行操作。
如何理解呢
想象一下我们有一个装满各种形状圆形、矩形、三角形的盒子。现在我们想对这些形状进行不同的操作比如测量它们的面积或周长。使用访问者模式我们可以创建一个“测量工具”即访问者它知道如何与每种形状交互并获取所需的信息而不需要改变形状本身。
访问者模式的角色
访问者模式中的角色包括
Visitor访问者这是一个接口或抽象类声明了访问特定元素类时需要执行的操作。ConcreteVisitor具体访问者实现了Visitor接口或继承了Visitor抽象类实现了对元素类中每个元素的访问操作。Element元素这是一个接口或抽象类声明了一个接受访问者对象的方法通常是accept。ConcreteElement具体元素实现了Element接口或继承了Element抽象类并实现accept方法以接受访问者的访问。ObjectStructure对象结构能够枚举它的元素并可以提供一个高层接口以允许访问者访问它的元素。这通常是一个集合类如列表或树。
类图 代码示例
package com.polaris.designpattern.list3.behavioral.pattern09.visitor.classicdemo;import java.util.ArrayList;
import java.util.List;// Visitor 接口
interface Visitor {void visit(ConcreteElementA element);void visit(ConcreteElementB element);
}// ConcreteVisitor 类
class ConcreteVisitor implements Visitor {Overridepublic void visit(ConcreteElementA element) {System.out.println(Visiting ConcreteElementA: element.operationA());}Overridepublic void visit(ConcreteElementB element) {System.out.println(Visiting ConcreteElementB: element.operationB());}
}// Element 接口
interface Element {void accept(Visitor visitor);
}// ConcreteElementA 类
class ConcreteElementA implements Element {Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationA() {return elementA info...;}
}// ConcreteElementB 类
class ConcreteElementB implements Element {Overridepublic void accept(Visitor visitor) {visitor.visit(this);}public String operationB() {return elementB info...;}
}// ObjectStructure 类这里简单用ArrayList作为示例class ObjectStructure {private ListElement elements new ArrayList();public void add(Element element) {elements.add(element);}public void accept(Visitor visitor) {for (Element element : elements) {element.accept(visitor);}}
}// 客户端代码
public class VisitorPatternDemo {public static void main(String[] args) {ObjectStructure objectStructure new ObjectStructure();objectStructure.add(new ConcreteElementA());objectStructure.add(new ConcreteElementB());Visitor visitor new ConcreteVisitor();objectStructure.accept(visitor);}
}
/* Output:
Visiting ConcreteElementA: elementA info...
Visiting ConcreteElementB: elementB info...
*///~在这个示例中我们有一个Visitor接口和两个具体的访问者方法对应于两种不同类型的元素。我们还有两个实现了Element接口的ConcreteElement类它们各自有自己的操作。ObjectStructure类管理了一个Element对象的集合并提供了一个accept方法来遍历这些对象并接受访问者的访问。在客户端代码中我们创建了一个ObjectStructure对象并向其中添加了两个不同类型的元素。然后我们创建了一个ConcreteVisitor对象并使用它来访问ObjectStructure中的所有元素。
访问者模式的应用
访问者模式是一种设计模式它允许在不改变数据结构的前提下为数据结构中的每个元素定义新的操作。这种模式在需要为数据结构中的元素添加新行为但又不想修改这些元素所在类的情况下特别有用。
优点
扩展性好当需要为数据结构中的元素添加新操作时只需定义一个新的访问者类即可无需修改原有类。复用性好访问者模式可以通过为不同的数据结构定义相同的访问者接口实现操作的复用。灵活性好访问者模式将数据结构与作用于结构上的操作解耦使得操作集合可以相对自由地演化而不影响系统的数据结构。符合单一职责原则每个访问者只负责一种操作使代码更加清晰和易于维护。
缺点
破坏封装在访问者模式中具体元素需要向访问者公开其内部状态和方法这可能会破坏对象的封装性。增加新数据结构困难当需要为新的数据结构添加访问者时需要在访问者接口中添加新的方法这可能会增加代码的复杂性。具体元素变更困难如果具体元素的内部结构发生变化可能需要修改所有相关的访问者类这可能会增加维护成本。
使用场景
电商网站商品分类与操作电商网站通常有大量的商品这些商品可以按照不同的属性进行分类。使用访问者模式可以定义一个访问者对象它能够访问不同类型的商品对象并根据需要执行不同的操作如按照价格排序、根据品牌筛选等。图形编辑器的操作处理在图形编辑器中有多种图形元素如线条、圆形、矩形等。访问者模式允许定义一个访问者对象它能够访问这些图形元素并执行不同的操作如移动、缩放、旋转或改变颜色等。编译器和解释器设计在编译器或解释器的设计中抽象语法树AST是一个常见的数据结构。使用访问者模式可以为AST中的不同节点类型定义不同的访问者以执行如类型检查、代码优化、代码生成等操作。 将源程序表示为一个抽象语法树编译器需要在抽象语法树上实施某些操作以进行“静态语义分析”例如检查是否所有的变量都已经被定义了。他也需要生成代码。因此他可能要定义许多操作以进行类型检查、代码优化、流程分析检查变量是否在使用前被赋初值等等。此外还可以使用抽象语法树进行优美格式打印、程序重构、code instrumentation(代码插装见下面note注释内容)以及对程序进行多种度量。 这些操作大多要求对不同的节点进行不同的处理。例如对代表赋值语句的结点的处理就不同于对代表变量或算术表达式的结点的处理。 因此有用于赋值语句的类有用于变量访问的类还有用于算术表达式的类等等。结点类的集合当然依赖于被编译的语言但对于一个给定的语言其变化不大即已有的数据结构变化不大或不变。 note: Code instrumentation代码仪器化是一种软件开发领域的技术。详细解释如下 定义 Code instrumentation涉及向代码中插入特定的指令或代码片段以便在程序执行过程中收集各种信息或执行特定的任务。 用途 调试通过插入额外的代码可以更容易地跟踪和调试程序的行为。性能分析插入的代码可以收集程序的性能数据如执行时间、内存使用等。代码覆盖率分析用于确定哪些代码在测试过程中被实际执行过。安全检查可以插入用于检测潜在安全问题的代码。 实现 通过在代码中嵌入仪器化代码开发人员可以更深入地了解程序的执行过程并获取关键的运行时信息。 其他表述 Code instrumentation有时也被称为**“代码插装”或“代码插桩”**。 应用实例 在自动化测试和内部质量保证QA工具中code instrumentation被用于基础设施、实施和维护以及支持代码覆盖率的分析。 总结来说code instrumentation是一种通过向代码中插入特定指令或代码片段来收集信息或执行任务的软件开发技术它在调试、性能分析、代码覆盖率分析和安全检查等方面发挥着重要作用。 示例解析:博物馆的导览员
假设你是一家博物馆的导览员博物馆里有很多不同类型的展品如绘画、雕塑和古代文物。作为导览员你需要为不同类型的展品提供不同的解说词。但是展品的种类可能会随着时间增加或减少而你不希望每次有新的展品加入时都要重新学习所有的解说词。
在这里展品可以看作是数据结构中的元素而导览员就是访问者。导览员访问者需要访问不同的展品元素并为它们提供解说词操作。
代码示例
下面是一个简单的Java代码示例用于模拟这个场景
package com.polaris.designpattern.list3.behavioral.pattern09.visitor.demo1;// 展品接口
interface Artifact {void accept(TourGuide tourGuide);
}// 绘画展品
class Painting implements Artifact {private String name;public Painting(String name) {this.name name;}Overridepublic void accept(TourGuide tourGuide) {tourGuide.visit(this);}public String getName() {return name;}
}// 雕塑展品
class Sculpture implements Artifact {private String name;public Sculpture(String name) {this.name name;}Overridepublic void accept(TourGuide tourGuide) {tourGuide.visit(this);}public String getName() {return name;}
}// 导览员访问者接口
interface TourGuide {void visit(Painting painting);void visit(Sculpture sculpture);// 如果以后有更多类型的展品可以在这里添加方法
}// 具体导览员类
class EnglishTourGuide implements TourGuide {Overridepublic void visit(Painting painting) {System.out.println(This is a painting called painting.getName() . It is beautiful!);}Overridepublic void visit(Sculpture sculpture) {System.out.println(This is a sculpture called sculpture.getName() . It is impressive!);}
}// 客户端代码
public class MuseumDemo {public static void main(String[] args) {// 创建展品 Artifact painting new Painting(Mona Lisa);Artifact sculpture new Sculpture(Thinker);// 创建导览员 TourGuide tourGuide new EnglishTourGuide();// 导览员访问展品 painting.accept(tourGuide);sculpture.accept(tourGuide);}
}/* Output:
This is a painting called Mona Lisa. It is beautiful!
This is a sculpture called Thinker. It is impressive!
*///~在这个示例中Artifact是展品接口Painting和Sculpture是具体的展品类。TourGuide是导览员接口EnglishTourGuide是具体的导览员类。 当新的展品类型出现时只需要实现Artifact接口并添加相应的accept方法然后在TourGuide接口中添加对应的visit方法即可而不需要修改已经存在的展品类和导览员类除了添加新的方法外。这样就实现了在不改变数据结构的前提下为数据结构中的每个元素定义新的操作。 note1: 当系统需要添加新的操作到已有的数据结构如不同的展品类型时我们可以通过增加一个新的访问者类来实现而无需修改原有的数据结构。 note2:当新的展品类型出现时需要 实现Artifact接口来定义新的展品类比如Ceramic代表陶瓷展品。在Artifact接口的实现类如Ceramic中实现accept方法以允许导览员TourGuide访问。修改TourGuide接口添加一个新的visit方法来处理新的展品类型比如void visit(Ceramic ceramic);。在TourGuide的实现类如EnglishTourGuide中实现新添加的visit方法以提供针对新展品类型的解说词。 这样当新的展品类型被添加到博物馆时导览员TourGuide就能够处理它而不需要修改已经存在的展品类和导览员类除了添加新的方法外。这种设计使得系统的扩展性很好能够轻松应对新的展品类型的添加。 ️上一篇:备忘录模式 | 下一篇:状态模式️ 设计模式-专栏️