适配模式

适配器模式

Convert the interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.

将一个类的接口变成客户端所期望的另一种接口,从而使原本因接口不匹配而无法一起工作的两个类能够在一起工作。

适配器模式的作用:

  • 接口转换,将原有的接口(或方法)转换成另一种接口;
  • 用新的接口包装一个已有的类;
  • 匹配一个老的组件到一个新的接口。

设计思想

适配器模式又叫变压器模式,也叫包装模式(Wrapper),它的核心思想是将一个对象经过包装或转换后使它符合指定的接口,使得调用方可以像使用这接口的一般对象一样使用它。这一思想,在我们生活中可谓是处处可见,比如变压器插座,能让你像使用国内电器一样使用美标(110V)电器;还有就是各种转接头,如 MiniDP 转 HDMI 转接头、HDMI 转 VGA 线转换器、Micro USB 转 Type-C 转接头等。

适配器模式的类图如下:

enter image description here

Target 是一个接口类,是提供给用户调用的接口抽象,如上面示例中的 IHightPerson。Adaptee 是你要进行适配的对象类,如上面的 ShortPerson。Adapter 是一个适配器,是对 Adaptee 的适配,它将 Adaptee 的对象转换(或说包装)成符合 Target 接口的对象;如上面的 DecoratePerson,将 ShortPerson 的 getRealHeight 和 getShoesHeight 方法包装成 IHightPerson 的 getHeight 接口。

模型说明

设计要点

适配器模式中主要三个角色,在设计适配器模式时要找到并区分这些角色:

  • 目标(Target): 即你期望的目标接口,要转换成的接口。
  • 源对象(Adaptee): 即要被转换的角色,要把谁转换成目标角色。
  • 适配器(Adapter): 适配器模式的核心角色,负责把源对象转换和包装成目标对象。

优缺点

适配器模式的优点
  • 可以让两个没有关联的类一起运行,起着中间转换的作用。
  • 提高了类的复用。
  • 灵活性好,不会破坏原有的系统。
适配器模式的缺点
  • 如果原有系统没有设计好(如 Target 不是抽象类或接口,而一个实体类),适配器模式将很难实现。
  • 过多地使用适配器,容易使代码结构混乱,如明明看到调用的是 A 接口,内部调用的却是 B 接口的实现。
class Page:
    """
    电子书一页的内容
    """
    def __init__(self,pageNum):
        self.__pageNum = pageNum

    def getCountent(self):
        return ""+str(self.__pageNum)+"页内容...."

class CateLogue:
    """
    目录结构
    """
    def __init__(self,title):
        self.__title = title
        self.__chapters = []
        self.setChapter("第一章")
        self.setChapter("第二章")

    def setChapter(self,title):
        self.__chapters.append(title)

    def showInfo(self):
        print("标题"+self.__title)
        for chapter in self.__chapters:
            print(chapter)


class IBook:
    """
    电子书文档的接口类
    """
    def parseFile(self,filePath):
        pass

    def getCatalogue(self):
        pass

    def getCount(self):
        pass

    def getPage(self,pageNum):
        pass

class TxtBook(IBook):
    """
    TXT解析器
    """
    def parseFile(self,filePath):
        print(filePath+"文件解析成功")
        self.__pageCount = 500
        return True

    def getCatalogue(self):
        return CateLogue("TXT电子书")

    def getPageCount(self):
        return self.__pageCount

    def getPage(self,pageNum):
        return Page(pageNum)

class EpubBook(IBook):
    """
    EPUB解析器
    """
    def parseFile(self,filePath):
        #模拟文档的解析
        print(filePath+"文件解析成功")
        self.__pageCount = 800
        return True

    def getCatalogue(self):
        return CateLogue("Epub电子书")

    def getPageCount(self):
        return self.__pageCount

    def getPage(self, pageNum):
        return Page(pageNum)

class OutLine:
    """
    第三方PDF解析库的目录类
    """
    pass

class PdfPage:
    """
    PDF页
    """

    def __init__(self,pageNum):
        self.__pageNum = pageNum

    def getPageNum(self):
        return self.__pageNum

class ThirdPdf:
    """
    第三方PDF解析器
    """

    def __init__(self):
        self.__pageSize = 0

    def open(self,filePath):
        print("第三方解析PDF文件:"+filePath)
        self.__pageSize = 1000
        return True

    def getOutline(self):
        return OutLine()

    def pageSize(self):
        return self.__pageSize

    def page(self,index):
        return PdfPage(index)

class PdfAdaterBook(ThirdPdf,IBook):
    """
    PDF解析类
    """

    def parseFile(self,filePath):
        rtn = super().open(filePath)
        if(rtn):
            print(filePath+"解析文件成功")
        return rtn

    def getCatalogue(self):
        outline = super().getOutline()
        print("将Outline结构的目录转换成Catalogue结构的目录")
        return CateLogue("PDF电子书")

    def getPageCount(self):
        return super().pageSize()

    def getPage(self,pageNum):
        page = self.page(pageNum)
        print("将PdfPage的对象转换成Page的对象")
        return Page(page.getPageNum())

import os

class Reader:
    """
    阅读器
    """
    def __init__(self,name):
        self.__name = name
        self.__filePath = ""
        self.__curBook = None
        self.__curPageNum = -1

    def __initBook(self,filePath):
        self.__filePath = filePath
        extName = os.path.splitext(filePath)[1]
        if extName.lower() == ".epub":
            self.__curBook = EpubBook()
        elif extName.lower() == ".txt":
            self.__curBook = TxtBook()
        elif extName.lower() == ".pdf":
            self.__curBook = PdfAdaterBook()
        else:
            self.__curBook = None

    def openFile(self,filePath):
        self.__initBook(filePath)
        if self.__curBook is not None:
            rtn = self.__curBook.parseFile(filePath)
            if rtn:
                self.__curPageNum = 1
            return rtn
        return False

    def closeFile(self):
        print("关闭"+self.__filePath+"文件")
        return True

    def showCatalogue(self):
        catalogue = self.__curBook.getCatalogue()
        catalogue.showInfo()

    def prePage(self):
        return self.gotoPage(self.__curPageNum - 1)

    def nexPage(self):
        return self.gotoPage(self.__curPageNum + 1)

    def gotoPage(self,pageNum):
        if pageNum<1 or pageNum>self.__curBook.getPageCount():
            return None
        self.__curPageNum = pageNum
        print("显示第"+str(self.__curPageNum)+"")
        page = self.__curBook.getPage(self.__curPageNum)
        page.getCountent()
        return page

if __name__ == '__main__':
    reader = Reader("阅读器")
    if not reader.openFile("平凡的世界.txt"):
        pass

    reader.showCatalogue()
    reader.gotoPage(1)
    reader.nexPage()
    reader.closeFile()
    print()

    if not reader.openFile("平凡的世界.epub"):
        pass

    reader.showCatalogue()
    reader.gotoPage(5)
    reader.nexPage()
    reader.closeFile()
    print()

    if not reader.openFile("平凡的世界.pdf"):
        pass

    reader.showCatalogue()
    reader.gotoPage(10)
    reader.nexPage()
    reader.closeFile()

 

posted on 2020-04-07 18:27  不要挡着我晒太阳  阅读(184)  评论(0编辑  收藏  举报

导航