Als Material zum Erlernen von GoF-Entwurfsmustern scheint das Buch "Einführung in Entwurfsmuster, die in der erweiterten und überarbeiteten Java-Sprache gelernt wurden" hilfreich zu sein. Da die aufgeführten Beispiele jedoch auf JAVA basieren, habe ich dieselbe Vorgehensweise mit Python versucht, um mein Verständnis zu vertiefen.
Das Abstract Factory-Muster ist eines der von GoF (Gang of Four; 4 Banden) definierten Entwurfsmuster. Der Zweck besteht darin, die Wiederverwendung mehrerer Module zu optimieren, indem die APIs zum Generieren verwandter Instanzen zusammengefasst werden. Im Japanischen wird es oft als "abstrakte Fabrik" übersetzt. Wird auch als Kit-Muster bezeichnet
UML class and sequence diagram UML class diagram (Das Obige wird aus Wikipedia zitiert)
Das Abstract Factory-Muster scheint ein abstraktes Produkt zu sein, indem abstrakte Teile aus ** abstract factory ** kombiniert werden. Tatsächlich möchte ich den Python-Implementierungscode von Abstract Factory ausführen, um eine Vorstellung von der ** abstrakten Factory ** zu bekommen. Das hier aufgenommene Beispielprogramm erstellt eine Sammlung von Links mit einer hierarchischen Struktur als HTML-Datei.
--Wenn Sie im ListFactory-Modus arbeiten, wird eine HTML-Datei mit Links im Listenformat generiert.
Lassen Sie uns zunächst den Code ausführen, der die ** Link-basierte ** Webseite erstellt.
$ python Main.py ListFactory
[LinkPage.html] was created.
Eine Datei namens "LinkPage.html" wurde generiert. Als ich das Erscheinungsbild mit einem Webbrowser überprüfte, sah es so aus.
Lassen Sie uns als Nächstes den Code ausführen, der eine ** tabellenbasierte ** Webseite erstellt.
$ python Main.py TableFactory
[LinkPage.html] was created.
Eine Datei namens "LinkPage.html" wurde generiert. Als ich das Erscheinungsbild mit einem Webbrowser überprüfte, sah es so aus.
Ähnlicher Code wurde in das Git-Repository hochgeladen. https://github.com/ttsubo/study_of_design_pattern/tree/master/AbstractFactory
--Verzeichnisaufbau
.
├── Main.py
└── factory
├── __init__.py
├── factory.py
├── listfactory
│ ├── __init__.py
│ └── list_factory.py
└── tablefactory
├── __init__.py
└── table_factory.py
Die Rolle "AbstractProduct" definiert die Schnittstelle der abstrakten Teile und Produkte, die durch die Rolle "AbstractFactory" erstellt wurden. Im Beispielprogramm übernehmen die Klassen "Link", "Tray" und "Page" diese Rolle.
factory/factory.py
import sys
from abc import ABCMeta, abstractmethod
... (snip)
class Item(metaclass=ABCMeta):
def __init__(self, caption):
self.caption = caption
@abstractmethod
def makeHtml(self):
pass
class Link(Item, metaclass=ABCMeta):
def __init__(self, caption, url):
super().__init__(caption)
self.url = url
class Tray(Item, metaclass=ABCMeta):
def __init__(self, caption):
super().__init__(caption)
self.tray = []
def add(self, item):
self.tray.append(item)
class Page(metaclass=ABCMeta):
def __init__(self, title, author):
self.title = title
self.author = author
self.content = []
def add(self, item):
self.content.append(item)
def output(self):
try:
filename = self.title + '.html'
writer = open(filename, 'w')
writer.write(self.makeHtml())
writer.close()
print("[" + filename + "]" + " was created.")
except Exception as e:
print(e)
sys.exit(1)
@abstractmethod
def makeHtml(self):
pass
Die Rolle "AbstractFactory" definiert die Schnittstelle zum Erstellen einer Instanz der Rolle "AbstractProduct". Im Beispielprogramm übernimmt die Factory-Klasse diese Rolle.
factory/factory.py
import sys
from abc import ABCMeta, abstractmethod
class Factory(metaclass=ABCMeta):
@abstractmethod
def createLink(self, caption, url):
pass
@abstractmethod
def createTray(self, caption):
pass
@abstractmethod
def createPage(self, title, author):
pass
... (snip)
Die "Client" -Rolle erledigt ihre Aufgabe nur über die Schnittstelle zwischen den Rollen "AbstractFactory" und "AbstractProduct". Die Rolle des "Kunden" kennt keine spezifischen Teile, Produkte oder Fabriken. Im Beispielprogramm übernimmt die Methode "startMain" diese Rolle.
Main.py
import sys
import inspect
import factory
def startMain(factoryObject):
asahi = factoryObject.createLink("Asahi", "http://www.asahi.com")
yomiuri = factoryObject.createLink("Yomiuri", "http://www.yomiuri.co.jp")
us_yahoo = factoryObject.createLink("Yahoo", "http://www.yahoo.com")
jp_yahoo = factoryObject.createLink("Yahoo!Japan", "http://www.yahoo.co.jp")
google = factoryObject.createLink("Google", "http://www.google.com")
excite = factoryObject.createLink("Excite", "http://www.excite.co.jp")
traynews = factoryObject.createTray("Newspaper")
traynews.add(asahi)
traynews.add(yomiuri)
trayyahoo = factoryObject.createTray("Yahoo!")
trayyahoo.add(us_yahoo)
trayyahoo.add(jp_yahoo)
traysearch = factoryObject.createTray("Search Engine")
traysearch.add(trayyahoo)
traysearch.add(excite)
traysearch.add(google)
page = factoryObject.createPage("LinkPage", "Hiroshi Yuki")
page.add(traynews)
page.add(traysearch)
page.output()
if __name__ == '__main__':
for _, plugin in inspect.getmembers(factory, inspect.isclass):
if plugin.__name__ == sys.argv[1]:
startMain(plugin())
Die Rolle "ConcreteProduct" implementiert die Schnittstelle für die Rolle "AbstractProduct". Im Beispielprogramm übernehmen die folgenden Klassen diese Rolle:
factory/listfactory/list_factory.py
from factory.factory import Factory, Link, Tray, Page
... (snip)
class ListLink(Link):
def __init__(self, caption, url):
super().__init__(caption, url)
def makeHtml(self):
return ' <li><a href="{}">{}</a></li>\n'.format(self.url, self.caption)
class ListTray(Tray):
def __init__(self, caption):
super().__init__(caption)
def makeHtml(self):
buf = []
buf.append('<li>\n')
buf.append(self.caption + '\n')
buf.append('<ul>\n')
for item in self.tray:
buf.append(item.makeHtml())
buf.append('</ul>\n')
buf.append('</li>\n')
return ''.join(buf)
class ListPage(Page):
def __init__(self, title, author):
super().__init__(title, author)
def makeHtml(self):
buf = []
buf.append('''
<html>
<head><title>{}</title></head>
'''.format(self.title))
buf.append('<body>\n')
buf.append('<h1>{}</h1>'.format(self.title))
buf.append('<ul>')
for item in self.content:
buf.append(item.makeHtml())
buf.append('</ul>')
buf.append('<hr><adress>{}</adress>'.format(self.author))
buf.append('</body>\n</html>\n')
return ''.join(buf)
factory/tablefactory/table_factory.py
from factory.factory import Factory, Link, Tray, Page
... (snip)
class TableLink(Link):
def __init__(self, caption, url):
super().__init__(caption, url)
def makeHtml(self):
return '<td><a href={}>{}</a></td>'.format(self.url, self.caption)
class TableTray(Tray):
def __init__(self, caption):
super().__init__(caption)
def makeHtml(self):
buf = []
buf.append('<td>')
buf.append('<table width="100%" border="1"><tr>')
buf.append('<td bgcolor="#cccccc" algin="center" colsapn="{}"><b>{}</b></td>'.format(len(self.tray), self.caption))
buf.append('</tr>\n')
buf.append('<tr>\n')
for item in self.tray:
buf.append(item.makeHtml())
buf.append('</tr></table>')
buf.append('</td>')
return ''.join(buf)
class TablePage(Page):
def __init__(self, title, author):
super().__init__(title, author)
def makeHtml(self):
buf = []
buf.append('''
<html>
<head><title>{}</title></head>
'''.format(self.title))
buf.append('<body>\n')
buf.append('<h1>{}</h1>'.format(self.title))
buf.append('<table width="80%" border="3">\n')
for item in self.content:
buf.append('<tr>{}</tr>'.format(item.makeHtml()))
buf.append('</table>')
buf.append('<hr><adress>{}</adress>'.format(self.author))
buf.append('</body>\n</html>\n')
return ''.join(buf)
Die Rolle "ConcreteFactory" implementiert die Schnittstelle für die Rolle "AbstractFactory". Im Beispielprogramm übernehmen die folgenden Klassen diese Rolle:
--ListFactory
Klasse
factory/__init__.py
from factory.listfactory.list_factory import ListFactory
from factory.tablefactory.table_factory import TableFactory
__all__ = [
"ListFactory",
"TableFactory"
]
factory/listfactory/list_factory.py
from factory.factory import Factory, Link, Tray, Page
class ListFactory(Factory):
def createLink(self, caption, url):
return ListLink(caption, url)
def createTray(self, caption):
return ListTray(caption)
def createPage(self, title, author):
return ListPage(title, author)
... (snip)
factory/tablefactory/table_factory.py
from factory.factory import Factory, Link, Tray, Page
class TableFactory(Factory):
def createLink(self, caption, url):
return TableLink(caption, url)
def createTray(self, caption):
return TableTray(caption)
def createPage(self, title, author):
return TablePage(title, author)
... (snip)
Recommended Posts