デコレータ/デコレータのデザインパターン

他のパターン説明を読んでください



問題



クラス全体ではなく、別のオブジェクトに(顧客に透過的な)追加の責任を割り当てること。



説明



問題の詳細を理解するには、特定の状況を考慮してください。 いくつかのオブジェクトがあるとします-オブジェクトのクラス「ボタン」に属する「ボタン」で、 追加の責任を割り当てる必要がありました。 このコンテキストでは、義務の下で、オブジェクトの特定の動作を指します。 ボタンの場合、画面に表示されるときのオブジェクトの動作を考慮することができます。 同時に、ボタン、ラベル、アイコンのフレームを表示するという追加の責任を検討します。 これらのすべての責任は、同時にかつ別々に課せられる必要があることを理解することが重要です。 明らかに、最初に頭に浮かぶのは、クラスの生成(継承メカニズム)です。 このタスクでは、これが解決策である可能性があります。「ボタン」クラスを、あらゆる種類の職務の組み合わせを組み合わせたさまざまなクラスのファミリー(2 3 -1 = 7)で拡張することです。 これらのクラスは、「Button_C_Label」、「Button_C_Frame」、「Button_C_Icon」、「Button_C_Label_I_Icon」、「Button_C_Frame_I_Icon」、「Button_C_Label_I_Frame」、「Button_C_Label_I_Frame」、「Button_C_Label_I_Frame」です。 そして、そのような義務が3つではなく、少なくとも10ある場合、そのような構造で作業することの不便さは言うまでもありません。 もちろん、この場合のクラスの生成は明らかに負けの選択肢です。 ただし、この状況から抜け出す方法があります-デコレータパターンです。



Decoratorパターンを使用すると、クラスを生成せずに、オブジェクトに新しい責任を動的に追加できます。 同時に、そのような構造での作業は、多くのクラスでの作業よりも便利で柔軟です。 これを行うために、装飾されたオブジェクトへの参照は、「Decorator」と呼ばれる別のクラスに配置されます。 さらに、デコレータと装飾されたオブジェクトの両方が同じインターフェースを実装しているため、複数のデコレータを相互にネストできるため、装飾されたオブジェクトに任意の数の新しい責任を追加できます。 デコレータは、装飾されたオブジェクトに外部呼び出しを転送し、追加の義務を課します。



実用的なタスク



「Decorator」パターンを使用して、ワイヤーフレームエディターフレームワークを実装します。 「デコレータ」を使用して、スキームの個々の要素をレンダリングする機能を課します。 2つのタイプのブロック-ターミナルブロック(開始/終了)とプロセスブロック(1つ以上のアクションを記述)を考えてみましょう。フレームと碑文でそれらを飾ります。



クラス図



クラス図を考えます。 AbstractBlockは、フローチャートの任意のブロックのインターフェイスであり、クライアントによって呼び出されるdraw()という単一のメソッドがあります。 これは、装飾されるオブジェクトのインターフェースであり、デコレーターのインターフェースでもあります。 TerminatorBlockおよびProcessBlock-抽象ブロックの改良。 AbstractBlockDectorator-ブロックデコレータの抽象クラス。 これはインターフェースではなく抽象クラスであることに注意してください。 実際、AbstractBlockDecoratorは、デフォルトでは、draw()メソッドで、装飾されるオブジェクトの対応するメソッドを委任します。 LabelBlockDecoratorおよびBorderBlockDecorator-ラベルおよびフレームのデコレーターとしてのブロックデコレーターの改良。 これらのクラスは、基本クラスのdraw()メソッドを再定義し、装飾されたオブジェクトに新しい責任を追加します(drawLabel()、drawBorder()メソッド)。







Pythonの実装



実装に関しては、少し発言したいと思います。 Pythonはインターフェースの記述をサポートしていないという事実により、それらをクラスとして記述することをお勧めしますが、これは抽象クラスではなくインターフェースであるということをプログラマーに強制することを忘れないでください。 リマインダーは、例外NotImplementedError()として作成できます。



# -*- coding: cp1251 -*-

class AbstractBlock:

"" "

"
""

def draw(self):

raise NotImplementedError();



class TerminatorBlock(AbstractBlock):

"" " (/, /)

"
""

def draw(self):

print "Terminator block drawing ... "



class ProcessBlock(AbstractBlock):

"" " - ( )

"
""

def draw(self):

print "Process block drawing ... "



class AbstractBlockDecorator(AbstractBlock):

"" "

"
""

def __init__(self, decoratee):

# _decoratee -

self._decoratee = decoratee



def draw(self):

self._decoratee.draw()



class LabelBlockDecorator(AbstractBlockDecorator):

"" "

"
""

def __init__(self, decoratee, label):

self._decoratee = decoratee

self._label = label



def draw(self):

AbstractBlockDecorator.draw(self)

self._drawLabel()



def _drawLabel(self):

print " ... drawing label " + self._label



class BorderBlockDecorator(AbstractBlockDecorator):

"" "

"
""

def __init__(self, decoratee, borderWidth):

self._decoratee = decoratee

self._borderWidth = borderWidth



def draw(self):

AbstractBlockDecorator.draw(self)

self._drawBorder()



def _drawBorder(self):

print " ... drawing border with width " + str(self._borderWidth)



#

tBlock = TerminatorBlock()

# -

pBlock = ProcessBlock()



# LabelDecorator

labelDecorator = LabelBlockDecorator(tBlock, "Label222" )



# BorderDecorator , LabelDecorator

borderDecorator1 = BorderBlockDecorator(labelDecorator, 22)



# BorderDecorator -

borderDecorator2 = BorderBlockDecorator(pBlock, 22)



labelDecorator.draw()

borderDecorator1.draw()

borderDecorator2.draw()



* This source code was highlighted with Source Code Highlighter .






誰かがついにpythonの例を入手しました。



ご注意



「デコレーター」パターンは「ラッパー」とも呼ばれます。



All Articles