Статья
Шаблон проектирования "Декоратор"

Шаблон проектирования "Декоратор"

10 мая 2020

Относится к структурным шаблонам.

Плюсы:
- позволяет динамически расширять фунциональность объекта
- данный подход гибче, чем наследование

Пример на PHP

Пусть имеется интерфейс IceCream и базовый класс BaseIceCream

interface IceCream
{
    public function getDescription(): string;
}

class BaseIceCream implements IceCream
{
    public function getDescription(): string
    {
        return "Ice cream";
    }
}

Расширим функциональность класса:

class IceCreamWithJam implements IceCream
{
    protected $iceCream;

    public function __construct(IceCream $iceCream)
    {
        $this->iceCream = $iceCream;
    }

    public function getDescription(): string
    {
        return $this->iceCream->getDescription() . ", with jam";
    }
}

class IceCreamWithNuts implements IceCream
{
    protected $iceCream;

    public function __construct(IceCream $iceCream)
    {
        $this->iceCream = $iceCream;
    }

    public function getDescription(): string
    {
        return $this->iceCream->getDescription() . ", with nuts";
    }
}

Использование:

$iceCream = new BaseIceCream();
echo $iceCream->getDescription(); // Ice cream

$iceCream = new IceCreamWithJam($iceCream);
echo $iceCream->getDescription(); // Ice cream, with jam

$iceCream = new IceCreamWithNuts($iceCream);
echo $iceCream->getDescription(); // Ice cream, with jam, with nuts


Пример на Go

package main

type IIceCream interface {
   GetDescription() string
}

type BaseIceCream struct {
}

func (i *BaseIceCream) GetDescription() string {
   return "Ice cream"
}

type IceCreamWithJam struct {
   iceCream IIceCream
}

func (i *IceCreamWithJam) GetDescription() string {
   return i.iceCream.GetDescription() + ", with jam"
}

type IceCreamWithNuts struct {
   iceCream IIceCream
}

func (i *IceCreamWithNuts) GetDescription() string {
   return i.iceCream.GetDescription() + ", with nuts"
}

func main() {
   baseIceCream := BaseIceCream{}
   baseIceCream.GetDescription() // Ice cream

   iceCreamWithJam := IceCreamWithJam{iceCream: &baseIceCream}
   iceCreamWithJam.GetDescription() // Ice cream, with jam
   
   iceCreamWithJamAndNuts := IceCreamWithNuts{iceCream: &iceCreamWithJam}
   iceCreamWithJamAndNuts.GetDescription() // Ice cream, with jam, with nuts
}


Источники:
http://designpatternsphp.readthedocs.io/ru/latest/Structural/Decorator/README.html
https://habrahabr.ru/company/mailru/blog/325492/