またまた面白いデザインパターンが登場。Bridgeパターンでは
- 機能のクラス階層
- 実装のクラス階層
という単語がしばしば登場する。本を読み、演習を解けば、この違いははっきりと分かるようになるし、これらを分ける理由も理解できる。
大事なことは、そもそもプログラミングするときに、
- 機能を書く ― 実装を書く
という発想がなく、単に
- これはクラスだからextends
- これはインターフェイスだからimplements
くらいしか考えてなかったことだろう。
(機能―実装 と クラス―インターフェイス とを対比させるのは明らかにおかしいけど)
機能/実装という見方でコードを読んだり書いたりすると、プログラマとして一歩前進できそうだ。
実装のクラス階層をOS依存で考える例や、継承と委譲の考え方の対比なんかも勉強になりました。
実行結果
+-------------+ |Hello, Japan.| +-------------+ +----------------+ |Hello, Universe.| +----------------+ +----------------+ |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| |Hello, Universe.| +----------------+ +----------------------------------+ |How many times have I been called?| |How many times have I been called?| |How many times have I been called?| |How many times have I been called?| +----------------------------------+ この味は うそをついてる味なんだなあ みつを < > < * > < * * > < * * * > | - | ## - | ## ## - | ## ## ## - | ## ## ## ## - | ## ## ## ## ## -
ソースコード
#!/usr/bin/env python # -*- coding: utf8 -*- # 機能のクラス階層 class Display: def __init__(self, impl): self.impl = impl def prepare(self): self.impl.rawPrepare() def draw(self): self.impl.rawDraw() def finish(self): self.impl.rawFinish() def display(self): self.prepare() self.draw() self.finish() class CountDisplay(Display): def multiDisplay(self, times): self.prepare() for i in xrange(times): self.draw() self.finish() #9-1 from random import randint class RandomDisplay(CountDisplay): def randomDisplay(self, max_times): self.multiDisplay(randint(0,max_times-1)) #9-3 class IncreaseDisplay(CountDisplay): def increaseDisplay(self, times): for i in xrange(times): self.multiDisplay(i) # 実装のクラス階層 class DisplayImpl: def __init__(self): raise Exception("Abstract class") def rawPrepare(self): raise NotImplementedError def rawDraw(self): raise NotImplementedError def rawFinish(self): raise NotImplementedError class StringDisplayImpl(DisplayImpl): def __init__(self, string): self.string = string def rawPrepare(self): self.__printLine() def rawDraw(self): print "|%s|" % self.string def rawFinish(self): self.__printLine() def __printLine(self): print '+%s+' % ''.join(['-' for i in xrange(len(self.string))]) #9-2 class FileDisplayImpl(DisplayImpl): import sys def __init__(self, filename): self.filename = filename self.fileobj = None def rawPrepare(self): try: self.fileobj = open(self.filename, 'r') except IOError, (errno, strerror): print "I/O error(%s): %s" % (errno, strerror) sys.exit(0) def rawDraw(self): self.fileobj.seek(0) # reset for line in self.fileobj: print line def rawFinish(self): self.fileobj.close() #9-3 class CharDisplayImpl(DisplayImpl): def __init__(self, head, body, foot): self.head = head self.body = body self.foot = foot def rawPrepare(self): print self.head, def rawDraw(self): print self.body, def rawFinish(self): print self.foot def main(): d1 = Display(StringDisplayImpl('Hello, Japan.')) d2 = CountDisplay(StringDisplayImpl('Hello, Universe.')) d1.display() d2.display() d2.multiDisplay(5) #9-1 d3 = RandomDisplay(StringDisplayImpl('How many times have I been called?')) d3.randomDisplay(5) #9-2 d4 = CountDisplay(FileDisplayImpl('mitsuo.txt')) d4.multiDisplay(1) #9-3 d5 = IncreaseDisplay(CharDisplayImpl('<','*','>')) d5.increaseDisplay(4) d6 = IncreaseDisplay(CharDisplayImpl('|','##','-')) d6.increaseDisplay(6) if __name__=='__main__': main()
0 件のコメント:
コメントを投稿