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 = """<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
    width="{pxwidth}px" height="{pxheight}px">"""

SVG_END = "</svg>\n"

SVG_RECTANGLE = """<rect x="{x}" y="{y}" width="{width}" \
height="{height}" fill="{fill}" stroke="{stroke}"/>"""

SVG_TEXT = """<text x="{x}" y="{y}" text-anchor="left" \
font-family="sans-serif" font-size="{fontsize}">{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="""<?xml version="1.0" encoding="UTF-8" standalone="no"?>
    <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
    <svg xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
    width="{pxwidth}px" height="{pxheight}px">"""
    SVG_END="</svg>\n"
    SVG_RECTANGLE="""<rect x="{x}" y="{y}" width="{width}" \
    height="{height}" fill="{fill}" stroke="{stroke}"/>"""
    SVG_TEXT="""<text x="{x}" y="{y}" text-anchor="left" \
    font-family="sans-serif" font-size="{fontsize}">{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()
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容