Presentation is loading. Please wait.

Presentation is loading. Please wait.

Decorator.

Similar presentations


Presentation on theme: "Decorator."— Presentation transcript:

1 Decorator

2 Motivational example GUI Toolkit

3 Motivational Example - GUI Toolkit
Several GUI elements, several decor options slider - top / bottom frame (different widths) We focus only on TextView 3

4 Motivational Example - GUI Toolkit
The GUI Toolkit contains the TextView component plain text display We want to customize this component "decorate" add slider add a frame etc. It would be useful: also have the original TextView available without decorations combine elemets slider + frame add some properties multiple times double frame add / remove specific properties at runtime "Layered structure" Maybe they can throw layers => slider inside or outside the frame 4

5 Motivational Example - GUI Toolkit
First solution attempt: "superclass" contains flags for all possible decorations the rendering method controls the presence of individual decorations class TextView { private bool isBordered; // Is TextView bordered? private int borderWidth; // Used only by bordered TextViews. private bool isScrollable; // Is TextView scrollable? private int scrollBarPosition; // Used only by scrollable TextViews. // ... public void Draw() /* Main drawing logic here. */ if (isBordered) /* Border drawing logic here. */ } if (isScrollable) /* Scrollbar drawing logic here. */ 5

6 Motivational Example - GUI Toolkit
First solution attempt: "superclass" we can add / remove properties at runtime ☺ we do not have to decorate at all ☺ no need to distinguish between ordinary and decorated instances ☺ we can combine the properties ☺ we can not use one property multiple times ☹ the instance knows it is decorated ☹ highly inflexible solution ☹ ☹ ☹ non-expandable without TextView ☹ We need to modify each class individually ☹ ☹ TextView Button Label Grid Panel ... ----- Meeting Notes (3/22/14 23:13) ----- Je to ošklivé The problem of multiple classes can be solved by a common ancestor yet problematic Problem - horizontal and vertical sliders code duplication Impossibility to choose decoration order 2. Proposal: to use some form of inheritance 6

7 Motivational Example - GUI Toolkit
Second solution attempt: inheritance base class - TextView derived - BorderedTextView, ScrollableTextView, BorderedScrollableTextView class TextView { // ... fields and other necessary textview logic public virtual void Draw() { /*...*/ } } class BorderedTextView : TextView { // ... border-specific data and logic public override void Draw() { /*...*/ } class ScrollableTextView : TextView { // ... scrolling-specific data and logic class BorderedScrollableTextView : ScrollableTextView { // ... border-specific data and logic, probably copied from BorderedTextView 7

8 Motivational Example - GUI Toolkit
Second solution attempt: inheritance static Can not change instance properties at runtime ☹ for each combination of properties, you need to create a new class We still can not arbitrarily choose the combination / order ☹ ☹ BorderedScrollableBorderedTextView ... ☹ leads to explosion of classes (n property → 2n classes) ☹ ☹ ☹ significantly increases the complexity of the system ☹ ☹ Changing properties at runtime means creating a new object, copying data and replacing it What about references to the original instance? Can I fix them all? Multiple inheritance in C ++ COMMON PREDICE TextView !!! name overlay? can not it get better? Return to the original layered idea 8

9 Motivational Example - GUI Toolkit
3. Return to the original idea of ​​the layers Delegation of frame / slider rendering to another object Idea: Separate individual decorations from the original object Framed textview has two parts: textview and frame The frame will hold a reference to the textview it decorates The new object will only worry about rendering the frame / slider, rendering the textview itself to the textview itself 9

10 Motivational Example - GUI Toolkit
Third solution: Decorator Common (abstract) ancestor - def. drawing interface A specific visual component Reference to the decorated object Delegation rendering to a decorated object Abstract decorator Specific decorators except delegations implement their own rendering Specific Decorator 10

11 Motivational Example - GUI Toolkit
Third solution Decorator public interface IVisualComponent { void Draw(); } class TextView : IVisualComponent public override void Draw() {  // draw window // ... abstract class Decorator : IVisualComponent  protected IVisualComponent vc;  // decorated component public Decorator(IVisualComponent vc) { this.vc = vc; public virtual void Draw() { vc.draw();           //delegation class ScrollDecorator : Decorator { public ScrollDecorator(IVisualComponent vc) : base(vc) { } public override void Draw()  { base.Draw();     // draw component DrawScrollBar(); } private void DrawScrollBar() { /*...*/ } // scrolling logic implementation // ... class BorderDecorator : Decorator { public BorderDecorator(IVisualComponent vc) drawScrollBar(); private void DrawBorder() { /*...*/ } 11

12 Motivational Example - GUI Toolkit
Third solution: Decorator decorators add individual features (decorations) we can add / remove properties at runtime ☺ we also have a common TextView ☺ decorations are independent of each other ☺ can be arbitrarily combined ☺ they can be used several times ☺ it's transparent ☺ from the client's point of view, there is no difference between ordinary and Decorated TextView TextView about decorations does not know at all VisualComponent licenseTextView = new BorderDecorator( new ScrollDecorator( new TextView())); // somewhere else: licenseTextView.Draw(); To get properties, we need interface support! 12

13 std::reverse_iterator
Motivational example std::reverse_iterator

14 Motivational example – std::reverse_iterator
Example of minimalistic implementation template <typename Iter> class reverse_iterator : public std::iterator< typename Iter::iterator_category, typename Iter::value_type, typename Iter::difference_type, typename Iter::pointer, typename Iter::reference> { private: Iter current; // decorated iterator public: explicit reverse_iterator(Iter&& p) : current{std::forward<Iter>(p)} {} void operator=(const reverse_iterator& other) { current = other.current; } typename Iter::reference operator*() const { auto tmp = current; return *--tmp; reverse_iterator& operator++() { --current; return *this; bool operator!=(const reverse_iterator& other) const { return current != other.current; }; template <typename Iter> typename reverse_iterator<Iter> make_reverse(Iter&& i) { return reverse_iterator<Iter>{std::forward<Iter>(i)}; } void print_elements(Iter begin, Iter end) { for (; begin != end; ++begin) std::cout << *begin << " "; int main(int argc, char* argv[]) { std::vector<int> v = { 1,2,3,4,5,6,7,8,9,10 }; print_elements( make_reverse(v.end()), make_reverse(v.begin())); std::cout << std::endl; 14

15 Decorator - Summary Structural pattern
Expands objects for additional behavior Extends specific objects, not classes expands the object dynamically, ie, at runtime Prefers the composition of objects before inheritance Delegation calls to the decorated object + custom functionality own added behavior may be before and after the delegated call 15

16 Decorator - structure and participants
Component - def. interface for objects that can be dynamically expanded ConcreteComponent - def. an object that can be dynamically expanded Decorator - an abstract front of all decorators contains a refinement to the object it decorates delegates all the calls to the decorated object ConcreteDecorator - Adds additional behavior to a component 16

17 Decorator - implementation
Usage typically using constructors chaining: The Decoder Interface must be the same as the Decorated Object Interface inheritance from a common ancestor or implementation of a common interface An abstract decorator can be omitted assuming we only need to add a single extension often when we need to expand the existing code delegation to the component is then done directly in this single decorator The Common Component should remain lightweight interface definition, not data storage otherwise the decorators will be too heavy Component c = new ConcreteDecoratorA( new ConcreteDecoratorB( new ConcreteComponent(...))); c.Operation(); 17

18 Decorator - advantages and disadvantages
greater flexibility for adding functionality than static inheritance properties can be added / removed at runtime multiple uses of the same decoration transparency there is no need to predict all the needs of the client simple incremental addition of functionality Disadvantages the component and its decorated version are not identical the decorator acts as a transparent encapsulation when using decorators do not rely on the identity of objects! many similar (small) objects potentially worse orientation in the code long strings of decorators can impact on performance 18

19 Real examples of using Decorator
Graphical toolkits Java Swing System.Windows.Controls Reading input, writing output System.IO.Stream java.io Component ConcreteComponent Decorator DataInputStream dis = new DataInputStream( new GzipInputStream( new BufferedInputStream( new FileInputStream("file.gz")))); dis.Read(...); ConcreteDecorator 19

20 Related Patterns Adapter
Decorator changes only the behavior of the object, not its interface The adapter will give the object a completely new interface Composite Decorator can be technically seen as a simplified Composite with a single component Decorator adds additional behavior is not intended to aggregate objects Strategy Decorator allows you to modify/customize the object essentially covers an object and changes its behavior while Strategy allows you to change the "guts" of the object a component in Strategy knows about possible extensions, not as Decorator: 20


Download ppt "Decorator."

Similar presentations


Ads by Google