设计模式三抽象工厂模式:边学边做个生成电子书的工具(python+dart)

139 阅读3分钟

抽象工厂,定义为 提供一个创建一系列相关或者相互依赖的对象的接口,而无需指定她们具体的类。核心是创建并返回指定的产品或者产品实例。从某种意义上看,抽象工厂其实是一个产品系列或者产品簇。切换产品簇的时候提供不同的抽象工厂。DAO模式常见的策略是抽象工厂。

这里实现仅作实例,我们的工具的真实场景可能又出入,假设 文件parser 里面分 docs 和nodoc两种情况吧。

dart实现代码

class BookInfo {
  String url = "";
  String content = "";
  String navItem = "";
  BookInfo(this.url, this.navItem, this.content);
}

class Book {
  BookInfo bookInfo;

  String fmt;

  Book(this.bookInfo, this.fmt) {
    print("init bookInfo");
  }

  makeBook() {
    print("make book" + fmt);
  }
}

class HtmlBook extends Book {
  HtmlBook(BookInfo bookInfo, String fmt) : super(bookInfo, fmt);

  @override
  makeBook() {
    print("html file  override ");
    return super.makeBook();
  }
}

class PdfBook extends Book {
  PdfBook(BookInfo bookInfo, String fmt) : super(bookInfo, fmt);

  @override
  makeBook() {
    print("pdf file");
    return super.makeBook();
  }
}

class MobiBook extends Book {
  MobiBook(BookInfo bookInfo, String fmt) : super(bookInfo, fmt);
  @override
  makeBook() {
    print("mobi book");
    return super.makeBook();
  }
}

class SimpleFactory extends Object {
  static createBook(BookInfo bookInfo, String fmt) {
    if (fmt.endsWith("pdf")) {
      print(" pdf xxx");
      return PdfBook(bookInfo, fmt);
    } else if (fmt.endsWith("html")) {
      print(" html xxx");
      return HtmlBook(bookInfo, fmt);
    } else if (fmt.endsWith("mobi")) {
      print(" mobi xxx");
      return MobiBook(bookInfo, fmt);
    } else {
      print("不支持其他格式");
    }
  }
}

abstract class ExportBook {
  exportBookApi(Book book);
}

class ExportBookPdf extends ExportBook {
  ExportBookPdf(Book book);
  @override
  exportBookApi(Book book) {
    print("implement of export pdf file");
    print(book.fmt);
  }
}

class ExportBookHtml extends ExportBook {
  ExportBookHtml(Book book);
  @override
  exportBookApi(Book book) {
    print("implement of export html file");
    print(book.fmt);
  }
}

class ExportBookMobi extends ExportBook {
  ExportBookMobi(Book book);
  @override
  exportBookApi(Book book) {
    print("implement of export mobi file");
    print(book.fmt);
  }
}

class ExportBookFactory {
  static ExportBook? exportBookFactory(Book book) {
    try {
      if (book.runtimeType.toString() == "PdfBook") {
        print("pdf book factory");
        return ExportBookPdf(book);
      } else if (book.runtimeType.toString() == "HtmlBook") {
        print("html book factory");
        return ExportBookHtml(book);
      } else if (book.runtimeType.toString() == "MobiBook") {
        print("mobi book factory");
        return ExportBookMobi(book);
      }
    } catch (e) {
      print("$e");
    }
    return null;
  }
}

// 抽象工厂 根据 url 里面是否含有docs 判断使用不同的parser或者指定。
// doc type url
//no doc type url
abstract class UrlParser {
  urlParserProcess();
}

class HtmlWithDocsParser extends UrlParser {
  @override
  urlParserProcess() {
    print("urlParserProcess    HtmlWithDocsParser ");
  }
}

class HtmlNoDocsParser extends UrlParser {
  @override
  urlParserProcess() {
    print("urlParserProcess    HtmlNoDocsParser ");
  }
}

// 创建一个工厂,将不同种类的文件跟paser对应起来 只是演示,不管真实场景是否适合
// 此处仅创建接口,具体由子类实现
abstract class BookParserFactory {
  // 创建book
  Book makeBook();
  // 调用解析器
  UrlParser urlParserProcess();
}

class DocsParserFactory implements BookParserFactory {
  late String url;

  DocsParserFactory(this.url);
  @override
  Book makeBook() => PdfBook(BookInfo(this.url, "navItem", "content"), "pdf");

  @override
  UrlParser urlParserProcess() => HtmlWithDocsParser();
}

class NotDocsParserFactory implements BookParserFactory {
  late String url;

  NotDocsParserFactory(this.url);

  @override
  Book makeBook() => MobiBook(BookInfo(this.url, "navItem", "content"), "mobi");

  @override
  UrlParser urlParserProcess() => HtmlNoDocsParser();
}

void main(List<String> args) {
  BookInfo bi = BookInfo("https://flutter.cn/docs", "nav_item", "content");

  Book thisBook = SimpleFactory.createBook(bi, "html");
  thisBook.makeBook();

  print("---------------------------------------");

  ExportBookFactory.exportBookFactory(thisBook)?.exportBookApi(thisBook);

  print("-------------------------abstract factory--------------");
  var notDocFactoryInstance = NotDocsParserFactory(thisBook.bookInfo.url);
  var bookm = notDocFactoryInstance.makeBook();
  var parsernotdocs = notDocFactoryInstance.urlParserProcess();

  var docFactoryInstance = DocsParserFactory(thisBook.bookInfo.url);
  var bookdoc = docFactoryInstance.makeBook();
  var parsertdocs = docFactoryInstance.urlParserProcess();

  parsertdocs.urlParserProcess();
  parsernotdocs.urlParserProcess();
  ;
}

运行结果截图

image.png

python 实现

import abc
from abc import *

class BookInfo(object):
    url = ""
    navItemContent = ""
    content = ""

    def __init__(self, url, navItem, content):
        self.url = url
        self.navItemContent = navItem
        self.content = content




class ExportBook(metaclass=abc.ABCMeta):
    @abstractmethod
    def exportBookApi(self,book):
        pass



class ExportBookPdf(ExportBook):
    def __init__(self, book):
        pass
    def exportBookApi(self,book):
        print("export pdf file by ExportBookApi ")
        print(book.fileExtension)
        print(book.bookInfo.url)


class ExportBookMobi(ExportBook):
    def __init__(self, book):
        pass
    def exportBookApi(self,book):
        print("export mobi file by ExportBookApi")
        print(book.fileExtension)

class ExportBookHtml(ExportBook):
    def __init__(self, book):
        pass
    def exportBookApi(self,book):
        print("export html file by ExportBookApi")
        print(book.fileExtension)


class ExportBookOperate(ExportBook):
    @staticmethod
    def exportBookFactory(book):
        if isinstance(book, MobiBook):
            return ExportBookMobi(book)
        elif isinstance(book,PdfBook):
            return ExportBookPdf(book)
        elif isinstance(book,HtmlBook):
            return ExportBookHtml(book)
        else:
            print("其他格式暂不支持")


class Book(metaclass=abc.ABCMeta):
    bookInfo = ""
    fileExtension = ""
    name = ""


    def __init__(self, bookInfo, fmt):
        self.bookInfo = bookInfo
        self.fileExtension = "." + fmt
        self.name = self.calcBookName(fmt)
        self.prepare()

    @abstractmethod
    def createBook(self):
        '''
        createBook
        :制作电子书:
        '''

    def calcBookName(self, fmt):
        '''
        从参数里面计算出书的名字
        :return:
        '''
        print(self.bookInfo.url)
        filenameTempString = self.bookInfo.url.split("//")[1]
        filenameTempString = filenameTempString.replace(".", "_")
        filenameTempString = filenameTempString.replace("-", "_")
        filenameTempString = filenameTempString.replace("/", "_")
        file_name = filenameTempString + self.fileExtension

        return file_name

    def prepare(self):
        """
        准备工作
        :return:
        """
        # print(__doc__)
        print(self.name)


class PdfBook(Book):
    """
    pdf book
    """
    def createBook(self):
        """
        make pdf book func
        :return:
        """
        print(PdfBook.__doc__)


class MobiBook(Book):
    """
    Mobi book
    """
    def createBook(self):
        """
        make mobi book func
        :return:
        """
        print(MobiBook.__doc__)


class HtmlBook(Book):
    """html book """

    def createBook(self):
        """
        make html book func
        :return:
        """
        print(HtmlBook.__doc__)


class SimpleFactory(object):
    """
    简单工厂
    """

    @staticmethod
    def createBook(bookInfo, fmt):
        """
        简单工厂
        :param bookInfo:
        :param fmt:
        :return:
        """

        if 'pdf' in fmt:
            print("create pdf factory")
            return PdfBook(bookInfo, fmt)
        elif "mobi" in fmt:
            print("create mobi file")
            return MobiBook(bookInfo, fmt)
        elif 'html' in fmt:
            print("create html file")
            return HtmlBook(bookInfo, fmt)
        else:
            print("暂时支持pdf 和mobi和html")



class UrlParser:
    @abstractmethod
    def urlParserProcess(self):
        pass

class HtmlWithDocsParser(UrlParser):
    def urlParserProcess(self):
        print("urlParserProcess    HtmlWithDocsParser ")

class HtmlNoDocsParser(UrlParser):
    def urlParserProcess(self):
        print("urlParserProcess    HtmlNoDocsParser ")


class BookParserFactory:
    @abstractmethod
    def  makeBook(self):
        pass
    @abstractmethod
    def  urlParserFactory(self):
        pass

class DocsParserFactory(BookParserFactory):
    url = ""
    def __init__(self,url):
        self.url = url

    def makeBook(self):

        return MobiBook(BookInfo(self.url,"navitem","content"),"mobi")

    def urlParserFactory(self):
        return HtmlWithDocsParser()


class NoDocsParserFactory(BookParserFactory):
    url = ""

    def __init__(self, url):
        self.url = url

    def makeBook(self):
        return PdfBook(BookInfo(self.url,"navitem","content"),"pdf")

    def urlParserFactory(self):
        return HtmlNoDocsParser()


print("test now")
bookInfo = BookInfo("https://flutter.cn/docs", "nav_item", "content")
bookCreate = SimpleFactory.createBook(bookInfo, 'pdf')

bookExport = ExportBookOperate.exportBookFactory(bookCreate)
bookExport.exportBookApi(bookCreate)
print("-----------------------------")

noDocsParserFactory = NoDocsParserFactory("https://flutter.cn/")
noDocbook = noDocsParserFactory.makeBook().createBook()
print(noDocbook)
noDocsParserFactory.urlParserFactory().urlParserProcess()

docsParserFactory = DocsParserFactory("https://flutter.cn/docs")
docBook = docsParserFactory.makeBook().createBook()
print(docBook)
docsParserFactory.urlParserFactory().urlParserProcess()

实现截图:

image.png

代码在之前的 简单工厂 工厂模式 基础上实现。