fbpx

Wzorce projektowe – Dekorator

Wzorce projektowe – Dekorator

Przyszedł czas na kolejny wzorzec projektowy. Wcześniej opisywałam już StrategięMetodę wytwórczą, czyli odpowiednio wzorzec czynnościowy i kreacyjny. Dzisiaj pierwszy przykład z grupy wzorców strukturalnych. Będzie nim Dekorator.

Na czym polega dekorator?

Dekorator jak już wspomniałam, należy do grupy wzorców strukturalnych. Wykorzystujemy go, aby stworzyć jak najbardziej elastyczną architekturę aplikacji. Bo w końcu, po co nam sztywna aplikacja, którą jest ciężko rozbudowywać.

Wzorzec ten rozbudowuje strukturę bez ingerencji w istniejące obiekty. Jest pomocny w sytuacji, gdy potrzebujemy dynamicznie rozszerzyć obiekt o jakąś funkcjonalność lub zmienić istaniejącą. Co to znaczy dynamicznie? To oznacza, że nie chcemy, aby każdy obiekt danej klasy miał tę funkcjonalność, tylko aby w konkretnych warunkach obiekt był o nią poszerzony. Wiem, trochę zagmatwane, ale postaram się to dokładniej wytłumaczyć w dalszej części tekstu.

Model

To jeden z nielicznych wzorców, który zaleca dziedziczenie klasy abstrakcyjnej po klasie abstrakcyjnej. Jest bardzo podobny do Adaptera. Opakowuje komponent, czyli klasę, którą chcemy rozszerzyć.

dekorator -model

Równie dobrze, zamiast klas abstrakcyjnych możemy zastosować interfejsy, też będzie to dobre rozwiązanie. Możemy zmieszać te dwie metody, czyli np. AbstractComponent będzie interfejsem Component a AbstractDecorator będzie klasą abstrakcyjną. To zależy od kontekstu zastosowania. Możemy go sobie dostosować do naszych potrzeb.

Zastosowanie

  1. Dekorator stosujemy w sytuacji, gdy nie do każdego obiektu danej klasy chcemy dodać jakąś funkcjonalność.
  2. Kiedy nie chcemy lub nie możemy zmienić struktury obiektów a potrzebujemy dokonać pewnych zmian w działaniu funkcji, lub rozszerzyć obiekt.
  3. Jeśli opcji rozszerzenia obiektu jest na tyle dużo, że tworzenie osobnej klasy dla każdej z nich byłoby niepraktyczne, biorąc pod uwagę ilość kombinacji.

Przykład

Poniższy przykład przedstawia Dekorator z użyciem podwójnej klasy abstrakcyjnej. W tym wypadku rozszerzamy istniejące już w obiekcie funkcje o dodatkowe rzeczy jak dodanie wykrzyknika do tytułu czy escape znaków specjalnych w treści. 

<?php

abstract class AbstractComponent {
    protected $title;
    protected $content;

    abstract function getTitle();
    abstract function getContent();
}

class Article extends AbstractComponent {
    function __construct($title, $content) {
        $this->title = $title;
        $this->content  = $content;
    }

    function getContent() {
        return $this->content;
    }
    function getTitle() {
        return $this->title;
    }
}

abstract class Decorator extends AbstractComponent {
    protected $article;
}

class TitleDecorator extends Decorator {
    public function __construct(Article $article) {
        $this->article = $article;
    }

    function getTitle() {
        return $this->article->title . "!";
    }

    function getTitle() {
        return $this->title;
    }
}

class ContentDecorator extends Decorator {
    public function __construct(Article $article) {
        $this->article = $article;
    }

    function getTitle() {
        return $this->title;
    }

    function getContent() {
        return htmlspecialchars($this->article->title);
    }
}

 
  $article = new Article('Tytuł', '<p>Treść</p>');
 
  $article = new TitleDecorator($article);
  $article = new ContentDecorator($article);
  
echo $article->getTitle() . ' ' . $article->getContent();

?>

Kolejny przykład to zastosowanie dekoratora z użyciem interfejsu i klasy abstrakcyjnej. W tym przypadku nie rozszerzamy istniejących funkcji, a dodajemy nowe.

<?php

interface Component {
    function getTitle();
    function getContent();
}

class Article implements Component {
    private $content;
    private $title;

    function __construct($title, $content) {
        $this->content = $content;
        $this->title  = $title;
    }

    function getContent() {
        return $this->content;
    }
    function getTitle() {
        return $this->title;
    }
}

abstract class Decorator implements Component {
    protected $article;

    public function __construct(Article $article) {
        $this->article = $article;
    } 
}

class TitleDecorator extends Decorator {
    function exclaimTitle() {
        return $this->article->title . "!";
    }

    function getTitle() {
        return $this->article->title;
    }
    function getContent() {
        return $this->article->content;
    }
}

class ContentDecorator extends Decorator {
    function escapeContent() {
        return htmlspecialchars($this->article->title);
    }

    function getTitle() {
        return $this->article->title;
    }
    function getContent() {
        return $this->article->content;
    }
}

  
  $article = new Article('Tytuł', '<p>Treść</p>');
 
  $titleDecorator = new TitleDecorator($article);
  $contentDecorator = new BookTitleStarDecorator($article);
 
  echo $titleDecorator->exclaimTitle();
  echo $contentDecorator->escapeContent();
 
 
?>

Infografika

dekorator - infografika



Zgarnij darmowy ebook i cotygodniową dawkę wiedzy

.
Magdalena Limanówka-Kuciel
magdalena@panizkomputerem.pl

Jestem programistką, która lubi mieć ręce pełne roboty. Do życia potrzebuje komputera z internetem i kubka gorącej kawy. Więcej na stronie o mnie.