2010年11月18日木曜日

第7章 Builderパターン : 複雑なインスタンスを組み立てる with python



BuilderパターンはTemplate Methodパターン(http://ksk77.blogspot.com/2010/11/3-template-method.html)に似ていて、Template Methodの応用と考えたほうが分かりやすいです。
異なる点は:

  • Template Method … テンプレートメソッドをスーパークラスが実装している
  • Builder … テンプレートメソッドを他のクラス(Director)が実装している


ここでいうテンプレートメソッドは、第3章におけるdisplay()に相当します。
Client(main)はBuilder役を知らず、Director役はBuilderしか知らない、という関係が結合度を小さくすることに寄与するのであります。

ソースコード
日本語エンコード処理まわりが非常に雑なのでその辺は参考にしないでください。

#!/usr/bin/env python
# -*- coding: utf8 -*-

class Director:
    def __init__(self, builder): self.builder = builder
    def construct(self):
        self.builder.makeTitle("Greeting")
        self.builder.makeString(u"朝から昼にかけて")
        self.builder.makeItems([u"おはようございます", u"こんにちは"])
        self.builder.makeString(u"夜に")
        self.builder.makeItems([u"こんばんは", u"おやすみなさい", u"さようなら"])
        self.builder.close()

class __Builder:
    def makeTitle(self, title): raise NotImplementedError
    def makeString(self, string): raise NotImplementedError
    def makeItems(self, items): raise NotImplementedError
    def close(self): raise NotImplementedError

import StringIO
class TextBuilder(__Builder):
    def __init__(self): self.buf = StringIO.StringIO()
    def makeTitle(self, title):
        print >>self.buf, "========================"
        print >>self.buf, "["+title+"]"
        print >>self.buf, ""
    def makeString(self, string):
        print >>self.buf, u"■"+string
        print >>self.buf, ""
    def makeItems(self, items):
        for i in items: print >>self.buf, u" ・"+i
        print >>self.buf, ""
    def close(self):
        print >>self.buf, "========================"
    def getResult(self):
        return self.buf.getvalue()

class HTMLBuilder(__Builder):
    def makeTitle(self, title):
        try:
            self.fsock = open(title+".html", 'w')
        except IOError, (errno, strerror):
            print "I/O error(%s): %s" % (errno, strerror)
        print >>self.fsock, "<html><head><title>"+title.encode("utf_8")+"</title></head><body>"
        print >>self.fsock, "<h1>"+title.encode("utf_8")+"</h1>"
    def makeString(self, string):
        print >>self.fsock, "<p>"+string.encode("utf_8")+"</p>"
    def makeItems(self, items):
        print >>self.fsock, "<ul>"
        for i in items: print >>self.fsock, "<li>"+i.encode("utf_8")+"</li>"
        print >>self.fsock, "</ul>"
    def close(self):
        print >>self.fsock, "</body></html>"
        self.fsock.close()
    def getResult(self):
        return self.fsock.name

def main():
    import sys, getopt
    opts,args = getopt.getopt(sys.argv[1:],'M:')
    for key,val in opts:
        if key == '-M':
            if val == "plain":
                textbuilder = TextBuilder()
                director = Director(textbuilder)
                director.construct()
                print textbuilder.getResult()
                return
            elif val == "html":
                htmlbuilder = HTMLBuilder()
                director = Director(htmlbuilder)
                director.construct()
                print htmlbuilder.getResult()+u"が作成されました"
                return
    print "Usage: python 7_builder.py -M plain"
    print "Usage: python 7_builder.py -M html"
    return

if __name__=='__main__': main()

0 件のコメント:

コメントを投稿