丁若云 发表于 2025-5-31 23:55:22

[设计模式/Java] 设计模式之访问者模式【24】




[*]访问者模式可以说是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 : 具体元素


[*]Keyboard
public class Keyboard implements ComputerPart {
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

[*]Monitor
public class Monitor implements ComputerPart {
   @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

[*]Mouse
public class Mouse implements ComputerPart {
    @Override
   public void accept(ComputerPartVisitor computerPartVisitor) {
      computerPartVisitor.visit(this);
   }
}

[*]Computer
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.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      【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!   

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页: [1]
查看完整版本: [设计模式/Java] 设计模式之访问者模式【24】