Editing Combined Patterns New

Decorator


Objective

Implementing additional responsibilities to an object, so dynamic, and provide a flexible alternative to extend the functionality of a subclass.

Function

Facilitate the addition of functionality to a class dynamically.

Structure

The client is always interested in CentralFunctionality.doSomething(). The client may, or may not, be interested in OptionOne.doSomething() and OptionTwo.doSomething(). Each of these classes always delegates to the base class Decorator, and that class always delegates to the object 'wrappee' content.

The structure that meets this pattern is shown in Figure 1

Responsive image

Figure 1: UML Diagram Decorator Pattern

Applications

The use of the Decorator pattern is recommended when:

  • The system requires that responsibilities be added dynamically and transparently to individual objects; that is, without affecting the other objects.

  • Withdrawal of responsibility without affecting operation is required.

  • Extensibility to subclass is impractical. Sometimes a large number of independent extensions is possible and would result in an explosion of subclasses for to support each combination.

Design Patterns Collaborators

  • A Decorator pattern is normally considered a single-component generated composite pattern; as a Decorator adds responsibilities additional.

  • The Decorator and Strategy patterns work together, in the area of variation of an object; one is in charge of its presentation while the other their form, respectively.

Scope of action

Applied at the object level.

Problem

To add a specific behavior or state to the individually and at run time, it is required to implement the inheritance; without However, this applies to an entire class in a static manner and the customer loses control.

Solution

The Decorator pattern forms the interface of the component that works as the boundary between a class and its respective subclasses, which is transparent to clients, the decorator class refers the order to the component and performs while transparency allows for recursively nesting decorators so that an unlimited number of aggregate liabilities are satisfied dynamically.

Diagram or Implementation

Responsive image

Figure 2: UML Diagram Decorator Pattern

Figure 2 explains the behaviour of the Decorator pattern by means of a sequence diagram.

  • Client Class performs an operation on the DecoratorA component.

  • The component DecoratorA performs the same operation on component DecoratorB.

  • The DecoradorB component class performs an action on ConcreteComponent.

  • The component type DecoratorB executes a decoration operation.

  • The component type DecoratorA executes a decoration operation.

  • The Client class receives as a result an object decorated by all the Decorators, which encapsulated the Component in several layers.


Study Cases


Interface System
Responsive image

Figure 3: UML Diagram Interface System


Responsive image

Figure 4: UML Diagram Interface System



Tourist Reservation System
Responsive image

Figure 5: UML Diagram Tourist Reservation System


Responsive image

Figure 6: UML Diagram Tourist Reservation System


Implementations of the decorator pattern:

    	
    		
"""
Attach additional responsibilities to an object dynamically. Decorators
provide a flexible alternative to subclassing for extending
functionality.
"""

import abc


class Component(metaclass=abc.ABCMeta):
    """
    Define the interface for objects that can have responsibilities
    added to them dynamically.
    """

    @abc.abstractmethod
    def operation(self):
        pass


class Decorator(Component, metaclass=abc.ABCMeta):
    """
    Maintain a reference to a Component object and define an interface
    that conforms to Component's interface.
    """

    def __init__(self, component):
        self._component = component

    @abc.abstractmethod
    def operation(self):
        pass


class ConcreteDecoratorA(Decorator):
    """
    Add responsibilities to the component.
    """

    def operation(self):
        # ...
        self._component.operation()
        # ...


class ConcreteDecoratorB(Decorator):
    """
    Add responsibilities to the component.
    """

    def operation(self):
        # ...
        self._component.operation()
        # ...


class ConcreteComponent(Component):
    """
    Define an object to which additional responsibilities can be
    attached.
    """

    def operation(self):
        pass


def main():
    concrete_component = ConcreteComponent()
    concrete_decorator_a = ConcreteDecoratorA(concrete_component)
    concrete_decorator_b = ConcreteDecoratorB(concrete_decorator_a)
    concrete_decorator_b.operation()


if __name__ == "__main__":
    main()    	
    	
    	
    		
class Book {
    private $author;
    private $title;
    function __construct($title_in, $author_in) {
        $this->author = $author_in;
        $this->title  = $title_in;
    }
    function getAuthor() {
        return $this->author;
    }
    function getTitle() {
        return $this->title;
    }
    function getAuthorAndTitle() {
      return $this->getTitle().' by '.$this->getAuthor();
    }
}

class BookTitleDecorator {
    protected $book;
    protected $title;
    public function __construct(Book $book_in) {
        $this->book = $book_in;
        $this->resetTitle();
    }   
    //doing this so original object is not altered
    function resetTitle() {
        $this->title = $this->book->getTitle();
    }
    function showTitle() {
        return $this->title;
    }
}

class BookTitleExclaimDecorator extends BookTitleDecorator {
    private $btd;
    public function __construct(BookTitleDecorator $btd_in) {
        $this->btd = $btd_in;
    }
    function exclaimTitle() {
        $this->btd->title = "!" . $this->btd->title . "!";
    }
}

class BookTitleStarDecorator extends BookTitleDecorator {
    private $btd;
    public function __construct(BookTitleDecorator $btd_in) {
        $this->btd = $btd_in;
    }
    function starTitle() {
        $this->btd->title = Str_replace(" ","*",$this->btd->title);
    }
}

  writeln('BEGIN TESTING DECORATOR PATTERN');
  writeln('');

  $patternBook = new Book('Gamma, Helm, Johnson, and Vlissides', 'Design Patterns');
 
  $decorator = new BookTitleDecorator($patternBook);
  $starDecorator = new BookTitleStarDecorator($decorator);
  $exclaimDecorator = new BookTitleExclaimDecorator($decorator);
 
  writeln('showing title : ');
  writeln($decorator->showTitle());
  writeln('');
 
  writeln('showing title after two exclaims added : ');
  $exclaimDecorator->exclaimTitle();
  $exclaimDecorator->exclaimTitle();
  writeln($decorator->showTitle());
  writeln('');
 
  writeln('showing title after star added : ');
  $starDecorator->starTitle();
  writeln($decorator->showTitle());
  writeln('');
 
  writeln('showing title after reset: ');
  writeln($decorator->resetTitle());
  writeln($decorator->showTitle());
  writeln('');

  writeln('END TESTING DECORATOR PATTERN');

  function writeln($line_in) {
    echo $line_in."
"; }
    	
    		
// 1. "lowest common denominator"
interface Widget {
    void draw();
}

// 3. "Core" class with "is a" relationship
class TextField implements Widget {
    private int width, height;

    public TextField(int width, int height) {
        this.width = width;
        this.height = height;
    }
    public void draw() {
        System.out.println("TextField: " + width + ", " + height);
    }
}

// 2. Second level base class with "isa" relationship
abstract class Decorator implements Widget {
    // 4. "has a" relationship
    private Widget widget;

    public Decorator(Widget widget) {
        this.widget = widget;
    }

    // 5. Delegation
    public void draw() {
        widget.draw();
    }
}

// 6. Optional embellishment
class BorderDecorator extends Decorator {
    public BorderDecorator(Widget widget) {
        super(widget);
    }
    public void draw() {
        // 7. Delegate to base class and add extra stuff
        super.draw();
        System.out.println("  BorderDecorator");
    }
}

// 6. Optional embellishment
class ScrollDecorator extends Decorator {
    public ScrollDecorator(Widget widget) {
        super(widget);
    }
    public void draw() {
        super.draw(); // 7. Delegate to base class and add extra stuff
        System.out.println("  ScrollDecorator");
    }
}

public class DecoratorDemo {
    public static void main(String[] args) {
        // 8. Client has the responsibility to compose desired configurations
        Widget widget = new BorderDecorator(new BorderDecorator(new ScrollDecorator(new TextField(80, 24))));
        widget.draw();
    }
}