Evgenii Legotckoi
Evgenii LegotckoiSept. 26, 2018, 6:01 a.m.

Structural Design Patterns - Decorator

Goals

  • Add additional features and functionality to the object dynamically. Decorators provide a flexible alternative to subclassing for extending functionality.
  • Client-specified decoration of the interface of the main object by recursively wrapping it.
  • Wrap the gift, put it in the box and wrap the box.

Problems

You want to add behavior or state to individual objects at run time. Inheritance is not possible because it is static and applies to the entire class.


Discussion

Let's say you're working with a user interface toolkit and you want to support adding borders and scrollbars to windows. You can define an inheritance hierarchy like...

But the Decorator pattern suggests giving the client the ability to specify any combination of "features".

Widget* aWidget = new BorderDecorator(
  new HorizontalScrollBarDecorator(
    new VerticalScrollBarDecorator(
      new Window( 80, 24 ))));
aWidget->draw();

This flexibility can be achieved with the following design

Another example of using cascaded (or chained) functions to create a custom object might look like this.

Stream* aStream = new CompressingStream(
  new ASCII7Stream(
    new FileStream("fileName.dat")));
aStream->putString( "Hello world" );

The solution to this class of problems involves encapsulating the original object inside an abstract wrapper interface. Both the decorator object and the main object inherit from this abstract interface. The interface uses recursive composition, allowing you to add an unlimited number of decorator "layers" to each main object.

Note that this pattern allows you to add functionality to an object, not to the object's interface. The interface presented to the client must remain constant as successive layers are specified.

Also note that the identity of the main object is now "hidden" inside the decorator object. Trying to directly access the underlying object is now a problem.

Structure

The client is always interested in the CoreFunctionality.doThis() method. The client may or may not be interested in OptionalOne.doThis() and OptionalTwo.doThis(). Each of these classes always delegates to the base Decorator class, and this class always delegates to the wrapper object.

Example

A decorator adds additional functionality to an object dynamically. Examples of decorators are decorations that are added to pine or spruce. Lights, garland, candy canes, glass ornaments, etc. These can be added to a tree to give it a festive look. Decorations do not change the tree itself, which can be recognized as a Christmas tree no matter what decorations are used. As an example of additional functionality, adding lights allows you to "light up" the Christmas tree.

Another example: an assault pistol is a lethal weapon. But you can apply certain "decorations" to make it more accurate, quiet and destructive.

Control List

  1. Make sure you have a context: one of the main (or optional) components, a few additional decorations or wrappers, and an interface common to all.
  2. Create the lowest level interface (LCD class) that makes all classes interchangeable.
  3. Create a second-level base class (Decorator) to support optional wrapper classes.
  4. The Core class and the Decorator class inherit from the LCD interface.
  5. The Decorator class declares a composition relation to the LCD interface, and this data member is initialized in its constructor.
  6. The Decorator class delegates the LCD object.
  7. Define a derived Decorator class for each additional embellishment.
  8. Derived Decorator classes implement their wrapper functionality - and - delegate to the base Decorator class.
  9. The client configures the type and order of the Core and Decorator objects.

Rules of thumb

  • An adapter provides a different interface to its object. The proxy provides the same interface. The decorator provides an extended interface.
  • The adapter changes the interface of the object, the Decorator extends the functionality of the object. The decorator is thus more transparent to the client. As a consequence, the Decorator supports recursive composition, which is not possible with pure adapters.
  • The composer and decorator have similar structure diagrams, reflecting the fact that both rely on recursive composition to organize an open number of objects.
  • A decorator can be thought of as a degenerate layout with a single component. However, the Decorator adds additional functionality - it is not designed for object aggregation.
  • Decorator is for adding functionality to objects without subclassing them. The purpose of the linker is not decoration, but presentation. These intentions differ from each other, but complement each other. Hence, the layout and decorator are often used together.
  • Composite can use Chain of Responsibility to allow components to access global properties through their parent. It can also use a Decorator to override these properties piece by piece.
  • Decorators and proxies have different purposes but similar structures. Both describe how to provide an abstraction layer to another object, and the implementations contain a reference to the object to which they direct requests.
  • A decorator allows you to change the representation of an object.
We recommend hosting TIMEWEB
We recommend hosting TIMEWEB
Stable hosting, on which the social network EVILEG is located. For projects on Django we recommend VDS hosting.

Do you like it? Share on social networks!

Comments

Only authorized users can post comments.
Please, Log in or Sign up
AD

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:50points,
  • Rating points-4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:80points,
  • Rating points4
m

C ++ - Test 004. Pointers, Arrays and Loops

  • Result:20points,
  • Rating points-10
Last comments
ИМ
Игорь МаксимовNov. 22, 2024, 10:51 p.m.
Django - Tutorial 017. Customize the login page to Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii LegotckoiNov. 1, 2024, 12:37 a.m.
Django - Lesson 064. How to write a Python Markdown extension Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZEOct. 19, 2024, 6:19 p.m.
Fb3 file reader on Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь МаксимовOct. 5, 2024, 5:51 p.m.
Django - Lesson 064. How to write a Python Markdown extension Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas5July 5, 2024, 9:02 p.m.
QML - Lesson 016. SQLite database and the working with it in QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Now discuss on the forum
m
moogoNov. 22, 2024, 6:17 p.m.
Mosquito Spray System Effective Mosquito Systems for Backyard | Eco-Friendly Misting Control Device & Repellent Spray - Moogo ; Upgrade your backyard with our mosquito-repellent device! Our misters conce…
Evgenii Legotckoi
Evgenii LegotckoiJune 25, 2024, 1:11 a.m.
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey1Nov. 15, 2024, 5:04 p.m.
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProjectJune 4, 2022, 1:49 p.m.
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…

Follow us in social networks