69 - 访问者模式 & 双分派

2021-10-08  本文已影响0人  舍是境界

讲到访问者模式,大部分书籍或者资料都会讲到 Double 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).
public abstract class ResourceFile {
  protected String filePath;
  public ResourceFile(String filePath) {
    this.filePath = filePath;
  }
}
public class PdfFile extends ResourceFile {
  public PdfFile(String filePath) {
    super(filePath);
  }
  //...
}
//...PPTFile、WordFile代码省略...
public class Extractor {
  public void extract2txt(PPTFile pptFile) {
    //...
    System.out.println("Extract PPT.");
  }
  public void extract2txt(PdfFile pdfFile) {
    //...
    System.out.println("Extract PDF.");
  }
  public void extract2txt(WordFile wordFile) {
    //...
    System.out.println("Extract WORD.");
  }
}
public class ToolApplication {
  public static void main(String[] args) {
    Extractor extractor = new Extractor();
    List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]);
    for (ResourceFile resourceFile : resourceFiles) {
      extractor.extract2txt(resourceFile);
    }
  }
  private static List<ResourceFile> listAllResourceFiles(String resourceDirectory) {
    List<ResourceFile> resourceFiles = new ArrayList<>();
    //...根据后缀(pdf/ppt/word)由工厂方法创建不同的类对象(PdfFile/PPTFile/WordFile)
    resourceFiles.add(new PdfFile("a.pdf"));
    resourceFiles.add(new WordFile("b.word"));
    resourceFiles.add(new PPTFile("c.ppt"));
    return resourceFiles;
  }
}

上文案例还有其他实现方式吗?

public abstract class ResourceFile {
  protected String filePath;
  public ResourceFile(String filePath) {
    this.filePath = filePath;
  }
  public abstract ResourceFileType getType();
}
public class PdfFile extends ResourceFile {
  public PdfFile(String filePath) {
    super(filePath);
  }
  @Override
  public ResourceFileType getType() {
    return ResourceFileType.PDF;
  }
  //...
}
//...PPTFile/WordFile跟PdfFile代码结构类似,此处省略...
public interface Extractor {
  void extract2txt(ResourceFile resourceFile);
}
public class PdfExtractor implements Extractor {
  @Override
  public void extract2txt(ResourceFile resourceFile) {
    //...
  }
}
//...PPTExtractor/WordExtractor跟PdfExtractor代码结构类似,此处省略...
public class ExtractorFactory {
  private static final Map<ResourceFileType, Extractor> extractors = new HashMap<>();
  static {
    extractors.put(ResourceFileType.PDF, new PdfExtractor());
    extractors.put(ResourceFileType.PPT, new PPTExtractor());
    extractors.put(ResourceFileType.WORD, new WordExtractor());
  }
  public static Extractor getExtractor(ResourceFileType type) {
    return extractors.get(type);
  }
}
public class ToolApplication {
  public static void main(String[] args) {
    List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]);
    for (ResourceFile resourceFile : resourceFiles) {
      Extractor extractor = ExtractorFactory.getExtractor(resourceFile.getType());
      extractor.extract2txt(resourceFile);
    }
  }
  private static List<ResourceFile> listAllResourceFiles(String resourceDirectory) {
    List<ResourceFile> resourceFiles = new ArrayList<>();
    //...根据后缀(pdf/ppt/word)由工厂方法创建不同的类对象(PdfFile/PPTFile/WordFile)
    resourceFiles.add(new PdfFile("a.pdf"));
    resourceFiles.add(new WordFile("b.word"));
    resourceFiles.add(new PPTFile("c.ppt"));
    return resourceFiles;
  }
}

小结

上一篇下一篇

猜你喜欢

热点阅读