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 件のコメント:
コメントを投稿