Factory Method概述

Factory Method - 图1

玩具代码案例 - 文件编辑器

工厂方法抽象父类

Editor

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. public abstract class Editor {
  6. private String title;
  7. private Document current;
  8. private List<Document> documents = new ArrayList<>();
  9. public String getTitle() {
  10. return title;
  11. }
  12. public void setTitle(String title) {
  13. this.title = title;
  14. }
  15. public void open(String file) {
  16. setTitle(file);
  17. current = createDocument(file);
  18. current.open();
  19. current.display();
  20. // multi-documents
  21. documents.add(current);
  22. }
  23. public void save() {
  24. current.save();
  25. }
  26. public void close() {
  27. current.close();
  28. }
  29. public void saveAll() {
  30. for (Document document : documents) {
  31. document.save();
  32. }
  33. }
  34. public void closeAll() {
  35. for (Document document : documents) {
  36. document.close();
  37. }
  38. }
  39. // Factory method
  40. protected abstract Document createDocument(String file);
  41. }

工厂方法具体子类

PdfEditor

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api.Editor;
  3. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  4. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.PdfDocument;
  5. public class PdfEditor extends Editor {
  6. protected Document createDocument(String file) {
  7. Document document = new PdfDocument();
  8. document.setFile(file);
  9. return document;
  10. }
  11. }

PngEditor

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api.Editor;
  3. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  4. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.PngDocument;
  5. public class PngEditor extends Editor {
  6. protected Document createDocument(String file) {
  7. Document document = new PngDocument();
  8. document.setFile(file);
  9. return document;
  10. }
  11. }

TxtEditor

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api.Editor;
  3. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  4. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.TxtDocument;
  5. public class TxtEditor extends Editor {
  6. protected Document createDocument(String file) {
  7. Document document = new TxtDocument();
  8. document.setFile(file);
  9. return document;
  10. }
  11. }

产品接口

Document

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.product.api;
  2. public abstract class Document {
  3. private String file;
  4. public String getFile() {
  5. return file;
  6. }
  7. public void setFile(String file) {
  8. this.file = file;
  9. }
  10. public abstract void open();
  11. public abstract void display();
  12. public abstract void save();
  13. public abstract void close();
  14. }

具体产品

PdfDocument

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  3. public class PdfDocument extends Document {
  4. public PdfDocument(){
  5. }
  6. @Override
  7. public void open() {
  8. System.out.println("打开Pdf文件" + this.getFile());
  9. }
  10. @Override
  11. public void display() {
  12. System.out.println("显示Pdf文件" + this.getFile());
  13. }
  14. @Override
  15. public void save() {
  16. System.out.println("存储Pdf文件" + this.getFile());
  17. }
  18. @Override
  19. public void close() {
  20. System.out.println("关闭Pdf文件" + this.getFile());
  21. }
  22. }

PngDocument

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  3. public class PngDocument extends Document {
  4. public PngDocument(){
  5. }
  6. @Override
  7. public void open() {
  8. System.out.println("打开PNG文件" + this.getFile());
  9. }
  10. @Override
  11. public void display() {
  12. System.out.println("显示PNG文件" + this.getFile());
  13. }
  14. @Override
  15. public void save() {
  16. System.out.println("存储PNG文件" + this.getFile());
  17. }
  18. @Override
  19. public void close() {
  20. System.out.println("关闭PNG文件" + this.getFile());
  21. }
  22. }

TxtDocument

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
  3. public class TxtDocument extends Document {
  4. public TxtDocument(){
  5. }
  6. @Override
  7. public void open() {
  8. System.out.println("打开Txt文件" + this.getFile());
  9. }
  10. @Override
  11. public void display() {
  12. System.out.println("显示Txt文件" + this.getFile());
  13. }
  14. @Override
  15. public void save() {
  16. System.out.println("存储Txt文件" + this.getFile());
  17. }
  18. @Override
  19. public void close() {
  20. System.out.println("关闭Txt文件" + this.getFile());
  21. }
  22. }

基于工厂方法模式的实现 - 仅支持单一文件类型的工厂方法编辑器

SingleEditorMain

  1. package online.javabook.gof.creational.patterns3.factorymethod.editor.app.good;
  2. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api.Editor;
  3. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl.PdfEditor;
  4. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl.PngEditor;
  5. import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl.TxtEditor;
  6. public class SingleEditorMain {
  7. public static void main(String[] args) {
  8. // product
  9. String fileName = "*.txt";
  10. // factory
  11. Editor editor = null;
  12. if (fileName.endsWith(".txt")) {
  13. editor = new TxtEditor();
  14. } else if (fileName.endsWith(".pdf")) {
  15. editor = new PdfEditor();
  16. }else if (fileName.endsWith(".png")) {
  17. editor = new PngEditor();
  18. }
  19. // do business
  20. editor.open("file1.txt");
  21. editor.open("file2.txt");
  22. editor.open("file3.txt");
  23. System.out.println("最后一次打开的文件:" +editor.getTitle());
  24. editor.saveAll();
  25. editor.closeAll();
  26. }
  27. }

Console

  1. 打开Txt文件file1.txt
  2. 显示Txt文件file1.txt
  3. 打开Txt文件file2.txt
  4. 显示Txt文件file2.txt
  5. 打开Txt文件file3.txt
  6. 显示Txt文件file3.txt
  7. 最后一次打开的文件:file3.txt
  8. 存储Txt文件file1.txt
  9. 存储Txt文件file2.txt
  10. 存储Txt文件file3.txt
  11. 关闭Txt文件file1.txt
  12. 关闭Txt文件file2.txt
  13. 关闭Txt文件file3.txt

基于工厂方法模式的实现 - 支持类型注册与多种文件类型的工厂方法编辑器

MultiEditor

package online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl;

import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.api.Editor;
import online.javabook.gof.creational.patterns3.factorymethod.editor.product.api.Document;
import org.apache.commons.io.FilenameUtils;

import java.util.HashMap;
import java.util.Map;

public class MultiEditor extends Editor {

    private Map<String, Class<? extends Document>> registers = new HashMap<>();

    // register methods
    public <T extends Class<? extends Document>> void registerDocumentClass(String extension, T documentClass) {
        registers.put(extension, documentClass);
    }

    protected Class<? extends Document> getRegisteredDocumentClass(String extension) {
        Class<? extends Document> documentClass = registers.get(extension);
        return documentClass;
    }

    // Factory method
    protected Document createDocument(String fileName) {

        String extension = FilenameUtils.getExtension(fileName);
        Class<? extends Document> documentClass = getRegisteredDocumentClass(extension);

        Document document = null;
        try {
            document = documentClass.newInstance();
            document.setFile(fileName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return document;
    }
}

MultiEditorMain

package online.javabook.gof.creational.patterns3.factorymethod.editor.app.good;

import online.javabook.gof.creational.patterns3.factorymethod.editor.creator.impl.MultiEditor;
import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.PdfDocument;
import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.PngDocument;
import online.javabook.gof.creational.patterns3.factorymethod.editor.product.impl.TxtDocument;

public class MultiEditorMain {
    public static void main(String[] args) {

        // factory
        MultiEditor editor = new MultiEditor();
        editor.registerDocumentClass("txt", TxtDocument.class);
        editor.registerDocumentClass("pdf", PdfDocument.class);
        editor.registerDocumentClass("png", PngDocument.class);

        // do business
        editor.open("file1.txt");
        editor.open("file2.pdf");
        editor.open("file3.png");

        System.out.println("最后一次打开的文件:" +editor.getTitle());
        editor.saveAll();
        editor.closeAll();
    }
}

Console

打开Txt文件file1.txt
显示Txt文件file1.txt
打开Pdf文件file2.pdf
显示Pdf文件file2.pdf
打开PNG文件file3.png
显示PNG文件file3.png
最后一次打开的文件:file3.png
存储Txt文件file1.txt
存储Pdf文件file2.pdf
存储PNG文件file3.png
关闭Txt文件file1.txt
关闭Pdf文件file2.pdf
关闭PNG文件file3.png