public abstract class ResourceFile { protected String filePath; public ResourceFile(String filePath) { this.filePath = filePath; } public abstract void extract2txt(); } public class PPTFile extends ResourceFile { public PPTFile(String filePath) { super(filePath); } @Override public void extract2txt() { //...省略一大坨从PPT中抽取文本的代码... //...将抽取出来的文本保存在跟filePath同名的.txt文件中... System.out.println("Extract PPT."); } } public class PdfFile extends ResourceFile { public PdfFile(String filePath) { super(filePath); } @Override public void extract2txt() { //... System.out.println("Extract PDF."); } } public class WordFile extends ResourceFile { public WordFile(String filePath) { super(filePath); } @Override public void extract2txt() { //... System.out.println("Extract WORD."); } } // 运行结果是: // Extract PDF. // Extract WORD. // Extract PPT. public class ToolApplication { public static void main(String[] args) { List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]); for (ResourceFile resourceFile : resourceFiles) { resourceFile.extract2txt(); } } 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 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; } abstract public void accept(Extractor extractor); } public class PdfFile extends ResourceFile { public PdfFile(String filePath) { super(filePath); } @Override public void accept(Extractor extractor) { extractor.extract2txt(this); } //... } //...PPTFile、WordFile跟PdfFile类似,这里就省略了... //...Extractor代码不变... public class ToolApplication { public static void main(String[] args) { Extractor extractor = new Extractor(); List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]); for (ResourceFile resourceFile : resourceFiles) { resourceFile.accept(extractor); } } 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; } abstract public void accept(Extractor extractor); abstract public void accept(Compressor compressor); } public class PdfFile extends ResourceFile { public PdfFile(String filePath) { super(filePath); } @Override public void accept(Extractor extractor) { extractor.extract2txt(this); } @Override public void accept(Compressor compressor) { compressor.compress(this); } //... } } //...PPTFile、WordFile跟PdfFile类似,这里就省略了... //...Extractor代码不变 public class ToolApplication { public static void main(String[] args) { Extractor extractor = new Extractor(); List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]); for (ResourceFile resourceFile : resourceFiles) { resourceFile.accept(extractor); } Compressor compressor = new Compressor(); for(ResourceFile resourceFile : resourceFiles) { resourceFile.accept(compressor); } } 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; } abstract public void accept(Visitor vistor); } public class PdfFile extends ResourceFile { public PdfFile(String filePath) { super(filePath); } @Override public void accept(Visitor visitor) { visitor.visit(this); } //... } //...PPTFile、WordFile跟PdfFile类似,这里就省略了... public interface Visitor { void visit(PdfFile pdfFile); void visit(PPTFile pdfFile); void visit(WordFile pdfFile); } public class Extractor implements Visitor { @Override public void visit(PPTFile pptFile) { //... System.out.println("Extract PPT."); } @Override public void visit(PdfFile pdfFile) { //... System.out.println("Extract PDF."); } @Override public void visit(WordFile wordFile) { //... System.out.println("Extract WORD."); } } public class Compressor implements Visitor { @Override public void visit(PPTFile pptFile) { //... System.out.println("Compress PPT."); } @Override public void visit(PdfFile pdfFile) { //... System.out.println("Compress PDF."); } @Override public void visit(WordFile wordFile) { //... System.out.println("Compress WORD."); } } public class ToolApplication { public static void main(String[] args) { Extractor extractor = new Extractor(); List<ResourceFile> resourceFiles = listAllResourceFiles(args[0]); for (ResourceFile resourceFile : resourceFiles) { resourceFile.accept(extractor); } Compressor compressor = new Compressor(); for(ResourceFile resourceFile : resourceFiles) { resourceFile.accept(compressor); } } 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; } }
感觉像是在耦合的地方解耦就是通过新加一个借助接口特性的类,动态根据参数决定其行为。这个参数是在main中传入的,所以就满足了不修改原来工具和资源类的OCP。
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)或者实现相同的接口。在不同的应用场景下,我们需要对这组对象进行一系列不相关的业务操作(抽取文本、压缩等),但为了避免不断添加功能导致类(PdfFile、PPTFile、WordFile)不断膨胀,职责越来越不单一,以及避免频繁地添加功能导致的频繁代码修改,我们使用访问者模式,将对象与操作解耦,将这些业务操作抽离出来,定义在独立细分的访问者类(Extractor、Compressor)中.
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; } }