Read the description of other patterns.
Problem
To impose additional duties (transparent for clients) on a separate object, and not on the class as a whole.
Description
For a more detailed understanding of the problem, consider a specific situation. Suppose there is some object - “button”, belonging to the “Button” object class, on which
additional responsibilities were required . Under responsibilities, in this context, refers to any features of the object. In the case of a button, you can consider the behavior of the object when it is displayed on the screen. At the same time, we will consider additional responsibilities - displaying the frame of the button, captions, icons. It is important to understand that all these responsibilities should be able to be imposed both simultaneously and separately. Obviously, the first thing that comes to mind is the generation of classes (the inheritance mechanism). For this task, it is possible and the way out is to expand the “Button” class with the family (2
3 -1 = 7) with various classes combining all possible combinations of duties. These are the classes: “Button_C_Description”, “Button_C_Frame”, “Button_C__Icon”, “Button_C__Incription_I_I_Icon”, “Button_C With Frame_I__Icon_”, “Button_C_R__Appointment_I__Frame”, “Button_C_A_ID_I_I_R_R__R__Red_I_R__E_____Frame_” And if such duties will be not three, but at least ten, not to mention the inconvenience of working with such a structure. Of course, the generation of classes in this case is obviously a losing option. However, there is a way out of this situation - the “Decorator” pattern.
The “Decorator” pattern allows you to dynamically add new responsibilities to an object, without resorting to the generation of classes. At the same time, working with a similar structure is more convenient and flexible than with a multitude of classes. For this, the reference to the object being decorated is placed in another class, called the "Decorator". Moreover, both the decorator and the object being decorated implement the same interface, which makes it possible to invest several decorators into each other, thereby adding to the object being decorated any number of new responsibilities. The decorator forwards external calls to the decorated object, accompanying them by imposing additional responsibilities.
')
Practical task
Using the “Decorator” pattern, we implement the frame of the
flowchart editor. We will use the “Decorator” to overlay the drawing features of the individual elements of the schemes. Consider two types of blocks - a terminal block (start / end) and a process block (describes one or more actions) and will decorate them with a frame and an inscription.
Class diagram
Consider the class diagram. AbstractBlock is the interface of any block diagram block that has a single method, draw (), called by the client. It is both an interface of the object being decorated and a decorator interface. TerminatorBlock and ProcessBlock - refine the abstract block. AbstractBlockDectorator is an abstract class of block decorator. Note that this is an abstract class, not an interface. The fact is that AbstractBlockDecorator, by default, in the draw () method delegates the corresponding method of the object to be decorated. LabelBlockDecorator and BorderBlockDecorator - refinements of block decorators, as a decorator of labels and frames. These classes override the base class's draw () method, adding new responsibilities to the object to be decorated (drawLabel (), drawBorder () methods).

Python implementation
Regarding the implementation, I would like to make a brief comment. Since Python does not support the description of interfaces, it is recommended to describe them as classes, but with a mandatory reminder to the programmer that this is an interface and not an abstract class. Reminder can be made as an exception 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 .
Someone finally waited for examples on the python.
Note
The “Decorator” pattern is also known under the name “Wrapper” / “Wrapper”.