九折技术 九折技术
首页
  • Go
  • MIT-6824
  • 算法与数据结构
  • 面向对象
  • 代码整洁
  • 重构
  • 设计模式
  • 学习
  • 技术
  • 人文
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub

HoldDie

长期有耐心,一切才刚刚开始!
首页
  • Go
  • MIT-6824
  • 算法与数据结构
  • 面向对象
  • 代码整洁
  • 重构
  • 设计模式
  • 学习
  • 技术
  • 人文
关于
  • 网站
  • 资源
  • 分类
  • 标签
  • 归档
GitHub
  • 代码整洁

  • 重构

  • 设计模式

    • 创建型-单例模式
    • 创建型-工厂模式
    • 创建型-建造者模式
    • 创建型-原型模式
    • 结构型-代理模式
    • 结构型-桥接模式
    • 结构型-装饰器模式
    • 结构型-适配器模式
    • 结构型-门面模式
    • 结构型-组合模式
    • 结构型-享元模式
    • 行为型-观察者模式
    • 行为型-模板模式
    • 行为型-策略模式
    • 行为型-责任链模式
    • 行为型-状态模式
    • 行为型-迭代器模式
    • 行为型-访问者模式
      • 行为型-备忘录模式
      • 行为型-命令模式
      • 行为型-解释器模式
      • 行为型-中介模式
    • 架构
    • 设计模式
    holddie
    2020-11-24

    行为型-访问者模式

    # 访问者模式

    • Visitor Design Pattern:Allows for one or more operation to be applied to a set of objects at runtime, decoupling the operations from the object structure.
    • 允许一个或多个操作应用到一组对象上,解耦操作和对象本身。
    • 访问者模式针对的是一组类型不同的对象(PDFFile,PPTFile,WordFile),尽管这组对象的类型不同,但是他们继承相同的父类(ResourceFile)或者实现相同的接口,在不同的应用场景下,我们需要对这组对象进行一系列不相关的业务操作(抽取、压缩),但为了避免不断增加功能导致的频繁代码改动,我们使用访问者模式,将对象与操作解耦,将这些业务操作抽离出来,定义在独立细分的访问者类中。
    • 访问者模式的关键是巧用重载函数,但是函数重载在大部分面向对象编程语言中是静态绑定的,调用类的那个重载函数,在编译器由参数的声明类型决定的,而非运行时,根据参数的实际类型决定的。
    • 访问者模式解决的痛点主要是需要动态绑定的类型,所以调用那个重载版本,其参数中的子类必须传入静态类型为目标子类的参数,并在方法中使用传入参数的动态绑定。

    访问者模式类图

    # 为什么支持双分派的语言不需要访问者模式?

    • 单分派(Single Dispatch):根据对象的运行时类型来决定执行哪个对象的方法;根据方法参数的编译时类型来决定执行对象的那个方法。
    • 双分派(Double Dispatch):根据对象的运行时类型来决定执行哪个对象的方法,;根据方法参数的运行时类型来决定执行对象的哪个方法。
    • Single Dispatch 之所以称为“Single”,是因为执行哪个对象的哪个方法,只跟“对象”的运行时类型有关。Double Dispatch 之所以称为“Double”,是因为执行哪个对象的哪个方法,跟“对象”和“方法参数”两者的运行时类型有关。
    • Single Dispatch 和 Double Dispatch 跟多态和函数重载直接相关。当前主流的面向对象编程语言(比如,Java、C++、C#)都只支持 Single Dispatch,不支持 Double Dispatch。
    • Java 支持多态特性,代码可以在运行时获得对象的实际类型(也就是前面提到的运行时类型),然后根据实际类型决定调用哪个方法。
    • 尽管 Java 支持函数重载,但 Java 设计的函数重载的语法规则是,并不是在运行时,根据传递进函数的参数的实际类型,来决定调用哪个重载函数,而是在编译时,根据传递进函数的参数的声明类型(也就是前面提到的编译时类型),来决定调用哪个重载函数。也就是说,具体执行哪个对象的哪个方法,只跟对象的运行时类型有关,跟参数的运行时类型无关。所以,Java 语言只支持 Single Dispatch。
    • 对于资源文件处理工具这个例子,如果工具提供的功能并不多,知识几个而已,那我们推荐使用工厂模式的实现方式,毕竟代码更加清晰、易懂。如果工具提供非常多的功能,比如有十几个,那我更推荐顺颂访问者模式,因为访问者模式需要定义的类要比工厂模式的实现方式少很多,类太多也会影响到代码的可维护性。
    • 一个对象调用另一个对象的方法,就相当于给它发送一条消息,这条消息起码要包含对象名、方法名和方法参数。

    代码执行结果

    
    public class ParentClass {
      public void f() {
        System.out.println("I am ParentClass's f().");
      }
    }
    
    public class ChildClass extends ParentClass {
      public void f() {
        System.out.println("I am ChildClass's f().");
      }
    }
    
    public class SingleDispatchClass {
      public void polymorphismFunction(ParentClass p) {
        p.f();
      }
    
      public void overloadFunction(ParentClass p) {
        System.out.println("I am overloadFunction(ParentClass p).");
      }
    
      public void overloadFunction(ChildClass c) {
        System.out.println("I am overloadFunction(ChildClass c).");
      }
    }
    
    public class DemoMain {
      public static void main(String[] args) {
        SingleDispatchClass demo = new SingleDispatchClass();
        ParentClass p = new ChildClass();
        demo.polymorphismFunction(p);//执行哪个对象的方法,由对象的实际类型决定
        demo.overloadFunction(p);//执行对象的哪个方法,由参数对象的声明类型决定
      }
    }
    
    //代码执行结果:
    I am ChildClass's f().
    I am overloadFunction(ParentClass p).
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    编辑
    #访问者模式
    上次更新: 2020/11/29, 15:11:00
    行为型-迭代器模式
    行为型-备忘录模式

    ← 行为型-迭代器模式 行为型-备忘录模式→

    最近更新
    01
    行为型-备忘录模式
    11-24
    02
    行为型-命令模式
    11-24
    03
    行为型-解释器模式
    11-24
    更多文章>
    Theme by Vdoing | Copyright © 2019-2020 HoldDie | MIT License
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式