序
- 访问者模式可以说是GOF23中设计模式中最复杂的一个,但日常开发中使用频率却不高。
所以说上帝喜欢简洁!
增删改查虽然简单,却是大部分程序员日常主要工作,是可以混饭吃的家伙式。
你技术再牛逼,企业用不到,那对于企业来说也没啥用,所以说合适的才是最好的。
但不常用不等于没有用,这一点的认识到。
概述:访问者模式 := Visitor Pattern ∈ 行为型模式
模式定义
访问者模式试图解决如下问题: > 一个类农场里面包含各种元素,例如有大雁,狗子,鸭子。而每个元素的操作却经常变换,一会让大雁排成一字,一会让大雁排成人字。
当大雁排成一字的时候狗子要排成S形状,鸭子要排成B形状,当大雁排成人字时候狗子要叫两声,鸭子要跳起来...。
但对农场这类有要求,第一:可以迭代这些元素,第二:里面的元素不能频繁变动,你不能一会把鸭子杀了吃了,一会又买回一匹马...,
如果是这样的话就不适合使用Visitor模式
如果我们不采用设计模式,那么就要频繁的修改这些元素类,违背了开闭原则,降低代码的可维护和扩展性。
解决在稳定数据结构和易变操作之间的【耦合】问题,使得操作可以独立于数据结构变化。
封装一些作用于某种数据结构中的各元素的操作,它可以在不改变这个数据结构的前提下,定义作用于其内部各个元素的新操作
在访问者模式(Visitor Pattern)中,我们使用了一个访问者类,它改变了元素类的执行算法。通过这种方式,元素的执行算法可以随着访问者改变而改变。
这种类型的设计模式属于行为型模式。根据模式,元素对象已接受访问者对象,这样访问者对象就可以处理元素对象上的操作。
适用场景
- 当你有个类,里面的包含各种类型的元素,这个类的结构比较稳定,不会经常增删不同类型的元素。而需要经常给这些元素添加新的操作的时候,考虑使用此设计模式。
当需要对一个对象结构中的对象执行多种不同的且不相关的操作时,尤其是这些操作需要避免"污染"对象类本身。
实现步骤
- 定义元素接口:声明一个接受访问者的方法。
- 创建具体元素:实现元素接口,每个具体元素类对应数据结构中的一个具体对象。
- 定义访问者接口(Visitor):声明一系列访问方法,一个访问方法对应数据结构中的一个元素类。
- 创建具体访问者(Concrete Visitor):实现访问者接口,为每个具体元素类的访问方法提供具体实现。
- 对象结构(Object Structure)(可选):
模式特点
优点
- 单一职责原则:访问者模式符合单一职责原则,每个类只负责一项职责。
- 扩展性:容易为数据结构添加新的操作。
- 灵活性:访问者可以独立于数据结构变化。
缺点
- 违反迪米特原则:元素需要向访问者公开其内部信息。
- 元素类难以变更:元素类需要维持与访问者的兼容。
- 依赖具体类:访问者模式依赖于具体类而不是接口,违反了依赖倒置原则。
使用建议
- 当对象结构稳定,但需要在其上定义多种新操作时,考虑使用访问者模式。
- 当需要避免操作"污染"对象类时,使用访问者模式封装操作。
- 访问者模式可以用于功能统一,如报表生成、用户界面显示、拦截器和过滤器等。
案例实践
CASE 生活场景-朋友家做客
- 做客场景:访问者(如您)访问朋友家,朋友作为元素提供信息,访问者根据信息做出判断。
CASE 计算机零部件
- 我们将创建一个定义接受操作的 `ComputerPart 接口。
- Keyboard、Mouse、Monitor 和 Computer 是实现了 ComputerPart 接口的实体类。
- 我们将定义另一个接口 ComputerPartVisitor,它定义了访问者类的操作。
- Computer 使用实体访问者来执行相应的动作。
- VisitorPatternDemo,我们的演示类使用 Computer、ComputerPartVisitor 类来演示访问者模式的用法。
ComputerPart : 元素接口
- public interface ComputerPart {
- public void accept(ComputerPartVisitor computerPartVisitor);
- }
复制代码 Keyboard|Monitor|Mouse|Computer implements ComputerPart : 具体元素
- public class Keyboard implements ComputerPart {
- @Override
- public void accept(ComputerPartVisitor computerPartVisitor) {
- computerPartVisitor.visit(this);
- }
- }
复制代码- public class Monitor implements ComputerPart {
- @Override
- public void accept(ComputerPartVisitor computerPartVisitor) {
- computerPartVisitor.visit(this);
- }
- }
复制代码- public class Mouse implements ComputerPart {
- @Override
- public void accept(ComputerPartVisitor computerPartVisitor) {
- computerPartVisitor.visit(this);
- }
- }
复制代码- public class Computer implements ComputerPart {
- ComputerPart[] parts;
-
- public Computer(){
- parts = new ComputerPart[] {new Mouse(), new Keyboard(), new Monitor()};
- }
-
-
- @Override
- public void accept(ComputerPartVisitor computerPartVisitor) {
- for (int i = 0; i < parts.length; i++) {
- parts[i].accept(computerPartVisitor);
- }
- computerPartVisitor.visit(this);
- }
- }
复制代码 ComputerPartVisitor : 访问者接口
- //访问者接口 : 声明一系列访问方法,一个访问方法对应数据结构中的一个元素类。
- public interface ComputerPartVisitor {
- public void visit(Computer computer);
- public void visit(Mouse mouse);
- public void visit(Keyboard keyboard);
- public void visit(Monitor monitor);
- }
复制代码 ComputerPartDisplayVisitor implements ComputerPartVisitor : 具体访问者
- public class ComputerPartDisplayVisitor implements ComputerPartVisitor {
- @Override
- public void visit(Computer computer) {
- System.out.println("Displaying Computer.");
- }
-
- @Override
- public void visit(Mouse mouse) {
- System.out.println("Displaying Mouse.");
- }
-
- @Override
- public void visit(Keyboard keyboard) {
- System.out.println("Displaying Keyboard.");
- }
-
- @Override
- public void visit(Monitor monitor) {
- System.out.println("Displaying Monitor.");
- }
- }
复制代码 Client
使用 ComputerPartDisplayVisitor 来显示 Computer 的组成部分。
- public class VisitorPatternDemo {
- public static void main(String[] args) {
- ComputerPart computer = new Computer();
- computer.accept(new ComputerPartDisplayVisitor());
- }
- }
复制代码out
- Displaying Mouse.
- Displaying Keyboard.
- Displaying Monitor.
- Displaying Computer.
复制代码 Y 推荐文献
X 参考文献
- 秒懂设计模式之访问者模式(Visitor Pattern) - Zhihu
- 设计模式: 访问者模式 - 概念、实现及spring中的访问者模式 - CSDN
- 访问者模式 - 菜鸟教程
本文作者: 千千寰宇
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |