Python デザインパターン サンプルコード Abstract Factory
結城 浩「Java言語で学ぶデザインパターン入門」をPython化
Python3(3.11)で動くソースコード(.pyファイル .ipynbファイル)あります
「anaconda3」on .py「PyCharm」.ipynb「Jupyter Notebook」
(2023-11-18)Python3.11で動作確認済み
【重要な注意】本ソースコードファイルを起動するには第2引数が必要です。ターミナルからPythonを起動するとき,普通はプロンプト「'>'」の後に次のようにタイプします。
>python abstract_factory_main.py listfactory.ListFactory(tablefactory.TableFactory)
ターミナルによっては'python'は'python3'になります。ソースコードファイル(スクリプトファイル)名称が第1引数です。第2引数は本プログラムに読み込むオプションです。
「PyCharm」では,次の枠に第2引数を設定します。
メニュー→run→Edit Configurations...→左下矢印と右上矢印の枠
ファイル名→Modify Run Configuration...→左下矢印と右上矢印の枠
画面によっては,Interpreter options: という枠です(左下矢印と右上矢印の枠)
引数が必要なところに「sys.argv[1]」を入れます。「Jupyter Notebook」では,自己テストに「sys.argv[1]=???」とする場合があります。そのときは「PyCharm」では,この行は必要ありません。「Jupyter Notebook」にこの行を入れるのは,ハードコードと言い,固有名詞や固有な数値をコマンドラインに埋め込むことは本来避けるべきですが,この場合はやむを得ないとしましょう。ちなみにこのコードでは第1引数のような扱いになっていますが,ターミナルのコマンドラインでは第2引数なので混乱しないように。
「sys.argv[1]」の前かまたは冒頭に「import sys」を忘れないように。
.pyではターミナルから実行されたとき自己テストが実行され,他のファイルから呼ばれたときは自己テストは無視されることも忘れないように。「Jupyter Notebook」では呼ばれる側を上側に置き,下側に参照されるようにします(本記事に関係ないかも)。
Item Page Factory (makeHTML) (add, output, makeHTML) (getFactory, createLink) ↑ ↑ (createTray, createPage) Link Tray (add) ↑ ↑ ↑ ↑ ListLink ListTray ListPage ListFactory (makeHTML)(makeHTML) (makeHTML) (createLink, createTray, createPage)
class Factory(object): @classmethod def getFactory(cls, classname): module, kls = classname.rsplit(".", 1) return getattr(__import__(module), kls)()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
#!/usr/bin/env python3 # -*- coding: utf-8 -*- #factory.py from abc import ABCMeta, abstractmethod class Item(metaclass = ABCMeta): def __init__(self, caption): self.caption = caption @abstractmethod def makeHTML(self): pass class Link(Item): def __init__(self, caption, url): super(Link, self).__init__(caption) self.url = url class Tray(Item): def __init__(self, caption): super(Tray, self).__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): self.filename = "{0}.html".format(self.title) writer = open(self.filename, "w") #writer.write(self.makeHTML().encode('shift-JIS')) writer.write(self.makeHTML()) writer.close() print("{0}を作成しました。".format(self.filename)) @abstractmethod def makeHTML(self): pass class Factory(metaclass = ABCMeta): @classmethod def getFactory(cls, classname): module, kls = classname.rsplit(".", 1) return getattr(__import__(module), kls)() # import modulename.classnameと等価 @abstractmethod def createLink(self, caption, url): pass @abstractmethod def createTray(self, caption): pass @abstractmethod def createPage(self, title, author): pass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
#!/usr/bin/env python3 # -*- coding: utf-8 -*- #listfactory.py import factory class ListFactory(factory.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) class ListLink(factory.Link): def __init__(self, caption, url): super(ListLink, self).__init__(caption, url) def makeHTML(self): return ' <li><a href="{0}">{1}</a></li>\n'\ .format(self.url, self.caption) class ListTray(factory.Tray): def __init__(self, caption): super(ListTray, self).__init__(caption) def makeHTML(self): self.buffer = [] self.buffer.append("<li>\n") self.buffer.append("{0}\n".format(self.caption)) self.buffer.append("<ul>\n") for item in self.tray: self.buffer.append(item.makeHTML()) self.buffer.append("</ul>\n") self.buffer.append("</li>\n") return "\n".join(self.buffer) class ListPage(factory.Page): def __init__(self, title, author): super(ListPage, self).__init__(title, author) def makeHTML(self): self.buffer = [] self.buffer.append( "<html><head><title>{0}</title></head>\n" .format(self.title)) self.buffer.append("<body>\n") self.buffer.append("<h1>{0}</h1>\n".format(self.title)) self.buffer.append("<ul>\n") for item in self.content: self.buffer.append(item.makeHTML()) self.buffer.append("</ul>\n") self.buffer.append( "<hr><address>{0}</address>".format(self.author)) self.buffer.append("</body></html>\n") return "\n".join(self.buffer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
#!/usr/bin/env python3 # -*- coding: utf-8 -*- #tablefactory.py import factory class TableFactory(factory.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) class TableLink(factory.Link): def __init__(self, caption, url): super(TableLink, self).__init__(caption, url) def makeHTML(self): return '<td><a href="{0}">{1}</a></td>\n'\ .format(self.url, self.caption) class TableTray(factory.Tray): def __init__(self, caption): super(TableTray, self).__init__(caption) def makeHTML(self): self.buffer = [] self.buffer.append("<td>") self.buffer.append( '<table width="100%" border="1"><tr>') self.buffer.append( '<td bgcolor="#cccccc" align="center"\ colspan="{0}"><b>{1}</b></td>' .format(len(self.tray), self.caption)) self.buffer.append("</tr>\n") self.buffer.append("<tr>\n") for item in self.tray: self.buffer.append(item.makeHTML()) self.buffer.append("</tr></table>") self.buffer.append("</td>") return "\n".join(self.buffer) class TablePage(factory.Page): def __init__(self, title, author): super(TablePage, self).__init__(title, author) def makeHTML(self): self.buffer = [] self.buffer.append( "<html><head><title>{0}</title></head>\n" .format(self.title)) self.buffer.append("<body>\n") self.buffer.append( "<h1>{0}</h1>\n".format(self.title)) self.buffer.append( '<table width="80%" boder="3">\n') for item in self.content: self.buffer.append( "<tr>{0}</tr>".format(item.makeHTML())) self.buffer.append("</table>\n") self.buffer.append( "<hr><address>{0}</address>".format(self.author)) self.buffer.append("</body></html>\n") return "\n".join(self.buffer)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
#!/usr/bin/env python3 # -*- coding: utf-8 -*- #abstract_factory_main.py from factory import * import sys def main(): factory = Factory.getFactory(sys.argv[1]) asahi = factory.createLink( "朝日新聞", "http://www.asahi.com/") yomiuri = factory.createLink( "読売新聞", "http://www.yomiuri.co.jp/") us_yahoo = factory.createLink( "Yahoo!", "http://www.yahoo.com/") jp_yahoo = factory.createLink( "Yahoo!Japan", "http://www.yahoo.co.jp/") excite = factory.createLink( "Exite", "http://www.excite.com/") google = factory.createLink( "Google", "http://www.google.com/") traynews = factory.createTray("新聞") traynews.add(asahi) traynews.add(yomiuri) trayyahoo = factory.createTray("Yahoo!") trayyahoo.add(us_yahoo) trayyahoo.add(jp_yahoo) traysearch = factory.createTray("サーチエンジン") traysearch.add(trayyahoo) traysearch.add(excite) traysearch.add(google) page = factory.createPage("LinkPage", "結城 浩") page.add(traynews) page.add(traysearch) page.output() if __name__== '__main__': main()
| ||||||||||
|