001创建型设计模式----抽象工厂模式

概述
用来创建复杂对象,这个复杂对象由许多小对象组成,这些小对象都属于某个特定的‘系列'

在GUI设计中可以设计一个“抽象控件工厂”,并射击三个“具体子类工厂”,

这三个具体的子类工厂分别为:MacWidgetFactory,XfaceWidgetFactory,WindowsWidgetFactory。他们属于同一系列(控件创建者),所以他们提供相同的chaugnjaing对象的方法(例如都提供make_button()创建按钮,change_position()指定控件的位置)。这三个具体的子类工厂将创建特定风格的控件,第一个是OS X风格,第二个是Linux风格,第三个是Windows风格。

因为这三个具体的子类都提供了相同的创建与修改方法,我们可以编写create_dialog()方法创建控件(该方法传入参数为三个具体工厂类中的一个),这样就可以通过传入create_dialog()的具体工厂类创建出具体风格的控件。

以下为伪代码(三个具体子类通过继承确认了统一套接口方法):

class MacWidgetFactory:

    def make_button(self):

        print('make_button_mac')

        pass

    def change_position(self):

        print('change_position_max')

        pass

class XfaceWidgetFactory(MacWidgetFactory):

    def make_button(self):

        print('maxk_button_linux')

        pass

    def change_position(self):

        print('change_position_linux')

        pass

class WindowsWidgetFactory(MacWidgetFactory):

    def make_button(self):

        print('window_button_windows')

        pass

    def change_position(self):

        print('change_position_windows')

        pass

def create_dialog(factory):

    return factory.make_button().change_position()

下面看两个具体实现:
1.抽象工厂模式版本一

import os

def main():
    textFilename=os.path.join("./",'text_diagram.txt')

    txtDiagrm=create_diagram(DiagramFactory())
    txtDiagrm.save(textFilename)
    print('wrote:{}'.format(textFilename))

    svgFilename=os.path.join('./','svg_diagram.svg')
    svgDiagram=create_diagram(SvgDiagramFactory())
    svgDiagram.save(svgFilename)
    print('wrote:{}'.format(svgFilename))

def create_diagram(factory):
    diagram=factory.make_diagram(30,7)
    rectangle=factory.make_rectangle(4,1,22,5,'yellow')
    text=factory.make_text(7,3,'Abstract Factory')
    diagram.add(rectangle)
    diagram.add(text)
    return diagram

class DiagramFactory:
    def make_diagram(self,width,height):
        return Diagram(width,height)

    def make_rectangle(self, x, y, width, height, fill="white",
                       stroke="black"):
        return Rectangle(x, y, width, height, fill, stroke)

    def make_text(self, x, y, text, fontsize=12):
        return Text(x, y, text, fontsize)

class SvgDiagramFactory(DiagramFactory):
    def make_diagram(self,width,height):
        return SvgDiagram(width,height)

    def make_rectangle(self, x, y, width, height, fill="white",
                       stroke="black"):
        return SvgRectangle(x,y,width,height,fill,stroke)

    def make_text(self,x,y,text,fontsize=12):
        return SvgText(x,y,text,fontsize)

BLANK = " "
CORNER = "+"
HORIZONTAL = "-"
VERTICAL = "|"

class Diagram:
    def __init__(self,width,height):
        self.width = width
        self.height = height
        self.diagram = _create_rectangle(self.width, self.height, BLANK)

    def add(self,component):
        for y, row in enumerate(component.rows):
            for x, char in enumerate(row):
                self.diagram[y + component.y][x + component.x] = char

    def save(self,filenameOrFile):
        file = None if isinstance(filenameOrFile, str) else filenameOrFile
        try:
            if file is None:
                file = open(filenameOrFile, "w", encoding="utf-8")
            for row in self.diagram:
                print("".join(row), file=file)
        finally:
            if isinstance(filenameOrFile, str) and file is not None:
                file.close()

def _create_rectangle(width,height,fill):
    rows = [[fill for _ in range(width)] for _ in range(height)]
    for x in range(1, width - 1):
        rows[0][x] = HORIZONTAL
        rows[height - 1][x] = HORIZONTAL
    for y in range(1, height - 1):
        rows[y][0] = VERTICAL
        rows[y][width - 1] = VERTICAL
    for y, x in ((0, 0), (0, width - 1), (height - 1, 0),
                 (height - 1, width - 1)):
        rows[y][x] = CORNER
    return rows

class Rectangle:
    def __init__(self,x,y,width,height,fill,stroke):
        self.x = x
        self.y = y
        self.rows = _create_rectangle(width, height,
                                      BLANK if fill == "white" else "%")

class Text:
    def __init__(self,x,y,text,fontsize):
        self.x = x
        self.y = y
        self.rows = [list(text)]

SVG_START = """

"""

SVG_END = "\n"

SVG_RECTANGLE = """"""

SVG_TEXT = """{text}"""

SVG_SCALE = 20

class SvgDiagram:
    def __init__(self,width,height):
        pxwidth = width * SVG_SCALE
        pxheight = height * SVG_SCALE
        self.diagram = [SVG_START.format(**locals())]
        outline = SvgRectangle(0, 0, width, height, "lightgreen", "black")
        self.diagram.append(outline.svg)

    def add(self,component):
        self.diagram.append(component.svg)

    def save(self,filenameOrFile):
        file=None if isinstance(filenameOrFile,str) else filenameOrFile
        try:
            if file is None:
                file = open(filenameOrFile, "w", encoding="utf-8")
            file.write("\n".join(self.diagram))
            file.write("\n" + SVG_END)
        finally:
            if isinstance(filenameOrFile, str) and file is not None:
                file.close()

class SvgRectangle:
    def __init__(self,x,y,width,height,fill,stroke):
        x *= SVG_SCALE
        y *= SVG_SCALE
        width *= SVG_SCALE
        height *= SVG_SCALE
        self.svg = SVG_RECTANGLE.format(**locals())

class SvgText:
    def __init__(self, x, y, text, fontsize):
        x *= SVG_SCALE
        y *= SVG_SCALE
        fontsize *= SVG_SCALE // 10
        self.svg = SVG_TEXT.format(**locals())

if __name__=="__main__":
    main()

2.抽象工厂模式版本二

import os

def main():
    textFilename=os.path.join("./",'text_diagram.txt')

    txtDiagrm=create_diagram(DiagramFactory)
    txtDiagrm.save(textFilename)
    print('wrote:{}'.format(textFilename))

    svgFilename=os.path.join('./','svg_diagram.svg')
    svgDiagram=create_diagram(SvgDiagramFactory)
    svgDiagram.save(svgFilename)
    print('wrote:{}'.format(svgFilename))

def create_diagram(factory):
    diagram=factory.make_diagram(30,7)
    rectangle=factory.make_rectangle(4,1,22,5,'yellow')
    text=factory.make_text(7,3,'Abstract Factory')
    diagram.add(rectangle)
    diagram.add(text)
    return diagram

class DiagramFactory:
    @classmethod
    def make_diagram(cls,width,height):
        return cls.Diagram(width,height)

    @classmethod
    def make_rectangle(cls,x,y,width,height,fill='white',stroke='black'):
        return cls.Rectangle(x,y,width,height,fill,stroke)

    @classmethod
    def make_text(cls,x,y,text,fontsize=12):
        return cls.Text(x,y,text,fontsize)

    BLANK=' '
    CORNER='+'
    HORIZONTAL='-'
    VERTICAL='|'

    class Diagram:
        def __init__(self, width, height):
            self.width = width
            self.height = height
            self.diagram = DiagramFactory._create_rectangle(self.width,
                                                            self.height, DiagramFactory.BLANK)

        def add(self, component):
            for y, row in enumerate(component.rows):
                for x, char in enumerate(row):
                    self.diagram[y + component.y][x + component.x] = char

        def save(self, filenameOrFile):
            file = (None if isinstance(filenameOrFile, str) else
                    filenameOrFile)
            try:
                if file is None:
                    file = open(filenameOrFile, "w", encoding="utf-8")
                for row in self.diagram:
                    print("".join(row), file=file)
            finally:
                if isinstance(filenameOrFile, str) and file is not None:
                    file.close()

    class Rectangle:
        def __init__(self, x, y, width, height, fill, stroke):
            self.x = x
            self.y = y
            self.rows = DiagramFactory._create_rectangle(width, height,
                                                         DiagramFactory.BLANK if fill == "white" else "%")

    class Text:
        def __init__(self, x, y, text, fontsize):
            self.x = x
            self.y = y
            self.rows = [list(text)]

    @staticmethod
    def _create_rectangle(width,height,fill):
        rows = [[fill for _ in range(width)] for _ in range(height)]
        for x in range(1, width - 1):
            rows[0][x] = DiagramFactory.HORIZONTAL
            rows[height - 1][x] = DiagramFactory.HORIZONTAL
        for y in range(1, height - 1):
            rows[y][0] = DiagramFactory.VERTICAL
            rows[y][width - 1] = DiagramFactory.VERTICAL
        for y, x in ((0, 0), (0, width - 1), (height - 1, 0),
                     (height - 1, width - 1)):
            rows[y][x] = DiagramFactory.CORNER
        return rows

class SvgDiagramFactory(DiagramFactory):
    SVG_START="""
    
    """
    SVG_END="\n"
    SVG_RECTANGLE=""""""
    SVG_TEXT="""{text}"""
    SVG_SCALE=20

    class Diagram:
        def __init__(self, width, height):
            pxwidth = width * SvgDiagramFactory.SVG_SCALE
            pxheight = height * SvgDiagramFactory.SVG_SCALE
            self.diagram = [SvgDiagramFactory.SVG_START.format(**locals())]
            outline = SvgDiagramFactory.Rectangle(0, 0, width, height,
                                                  "lightgreen", "black")
            self.diagram.append(outline.svg)

        def add(self, component):
            self.diagram.append(component.svg)

        def save(self, filenameOrFile):
            file = (None if isinstance(filenameOrFile, str) else
                    filenameOrFile)
            try:
                if file is None:
                    file = open(filenameOrFile, "w", encoding="utf-8")
                file.write("\n".join(self.diagram))
                file.write("\n" + SvgDiagramFactory.SVG_END)
            finally:
                if isinstance(filenameOrFile, str) and file is not None:
                    file.close()

    class Rectangle:
        def __init__(self,x,y,width,height,fill,stroke):
            x *= SvgDiagramFactory.SVG_SCALE
            y *= SvgDiagramFactory.SVG_SCALE
            width *= SvgDiagramFactory.SVG_SCALE
            height *= SvgDiagramFactory.SVG_SCALE
            self.svg = SvgDiagramFactory.SVG_RECTANGLE.format(**locals())

    class Text:
        def __init__(self,x,y,text,fontsize):
            x *= SvgDiagramFactory.SVG_SCALE
            y *= SvgDiagramFactory.SVG_SCALE
            fontsize *= SvgDiagramFactory.SVG_SCALE // 10
            self.svg = SvgDiagramFactory.SVG_TEXT.format(**locals())

if __name__=="__main__":
    main()

你可能感兴趣的:(001创建型设计模式----抽象工厂模式)