Decoratorパターンは前回のCompositeパターン
http://ksk77.blogspot.com/2010/11/11-composite.html
と同様、同一視がキーワードですね。
DecoratorパターンのUML(Fig 12-5 p.179)を見てみると、CompositeパターンのUML(Fig 11-3 p.164)とよく似ているのが分かります。
それもそのはずで、前回のファイルシステムの例で考えて見れば、ディレクトリを『飾り枠』としても同様の構造を記述できることが想像できます。またCompositeでは末端(Leaf)が分離され、Decoratorでは根っこ(ConcreteComponent)が分離されています。
Decoratorパターンは、言うなれば、中身が常に一つで、追加や取り出しが出来ないCompositeパターンでしょうか。…普通そんな風には考えないと思いますが。
Decoratorパターンの特徴は、どこを切ってもそこにはただ一つのComponentがあるという点でしょう。マトリョーシカのように。
--
SideBorderクラスのコンストラクタは引数の順番が逆な方が分かりやすいと思います。
あと今回は書籍内のコードを読まずに書いたので、実装が書籍に沿わないかもです。
実行結果
Hello, world. #Hello, world.# +---------------+ |#Hello, world.#| +---------------+ /+----------------+/ /|+--------------+|/ /||*+----------+*||/ /||*|konnichiwa|*||/ /||*+----------+*||/ /|+--------------+|/ /+----------------+/
ソースコード
#!/usr/bin/env python # -*- coding: utf8 -*- class Display: def __init__(self): raise Exception("Abstract class") def columns(self): raise NotImplementedError def rows(self): raise NotImplementedError def rowText(self, index): raise NotImplementedError def show(self): for i in xrange(self.rows()): print self.rowText(i) class StringDisplay(Display): def __init__(self, string): self.__string = string def columns(self): return len(self.__string) def rows(self): return 1 def rowText(self, index): return self.__string class Border(Display): _display = None class SideBorder(Border): def __init__(self, borderChar, display): self.__borderChar = borderChar self._display = display def columns(self): return self._display.columns() + 2 def rows(self): return self._display.rows() def rowText(self, index): return self.__borderChar + self._display.rowText(index) + self.__borderChar class FullBorder(Border): def __init__(self, display): self._display = display def columns(self): return self._display.columns() + 2 def rows(self): return self._display.rows() + 2 def rowText(self, index): if index == 0 or index == self.rows()-1: return "+" + "".join(["-" for i in xrange(self._display.columns())]) + "+" else: return "|" + self._display.rowText(index-1) + "|" def main(): # these data type are Display m_b1 = StringDisplay("Hello, world.") m_b2 = SideBorder("#", m_b1) m_b3 = FullBorder(m_b2) m_b4 = SideBorder("/", FullBorder(FullBorder(SideBorder("*", FullBorder(StringDisplay("konnichiwa")))))) m_b1.show() m_b2.show() m_b3.show() m_b4.show() if __name__=='__main__': main()
0 件のコメント:
コメントを投稿