主要将数据结构与数据操作分离

主要解决:稳定的数据结构和易变的操作耦合问题。
何时使用:需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,使用访问者模式将这些封装到类中。
如何解决:在被访问的类里面加一个对外提供接待访问者的接口。

案例

比如老师家访学生,不同科目的老师就是访问者,通过学生的描述,老师对同一个学生做出一个判断

  1. // 元素类
  2. class Student {
  3. constructor(name, chinese, math, english) {
  4. this.name = name
  5. this.chinese = chinese
  6. this.math = math
  7. this.english = english
  8. }
  9. accept(visitor) {
  10. visitor.visit(this)
  11. }
  12. }
  13. // 访问者类
  14. class ChineseTeacher {
  15. visit(student) {
  16. console.log(`语文${student.chinese}`)
  17. }
  18. }
  19. class MathTeacher {
  20. visit(student) {
  21. console.log(`数学${student.math}`)
  22. }
  23. }
  24. class EnglishTeacher {
  25. visit(student) {
  26. console.log(`英语${student.english}`)
  27. }
  28. }
  29. // 实例化元素类
  30. const student = new Student('张三', 90, 80, 60)
  31. // 实例化访问者类
  32. const chineseTeacher = new ChineseTeacher()
  33. const mathTeacher = new MathTeacher()
  34. const englishTeacher = new EnglishTeacher()
  35. // 接受访问
  36. student.accept(chineseTeacher)
  37. student.accept(mathTeacher)
  38. student.accept(englishTeacher)

总结

优点

  • 符合单一职责原则。
  • 优秀的扩展性。
  • 灵活性。

    缺点

  • 具体元素对访问者公布细节,违反了迪米特原则。

  • 具体元素变更比较困难。
  • 违反了依赖倒置原则,依赖了具体类,没有依赖抽象。

    场景

  • 对象结构中对象对应的类很少改变,但经常需要在此对象结构上定义新的操作。

  • 需要对一个对象结构中的对象进行很多不同的并且不相关的操作,而需要避免让这些操作”污染”这些对象的类,也不希望在增加新操作时修改这些类。

    注意事项:

  • 访问者可以对功能进行统一,可以做报表、UI、拦截器与过滤器。