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

Шаблон проектирования "Компоновщик"

18 мая 2020

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

Используется для компоновки объектов в древовидные структуры для представления иерархий, позволяя одинаково обращаться к отдельным объектам и к группе объектов.


Пример на PHP

Пусть имеется интерфейс Animal и 2 класса животных - Parrot и Crocodile, реализующих интерфейс Animal:

interface Animal
{
    public function __construct(string $name);
    public function getName(): string;
    public function setWeight(int $weight);
    public function getWeight(): int;
}

class Parrot implements Animal
{
    protected int $weight;
    protected string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setWeight(int $weight)
    {
        $this->weight = $weight;
    }

    public function getWeight(): int
    {
        return $this->weight;
    }
}

class Crocodile implements Animal
{
    protected int $weight;
    protected string $name;

    public function __construct(string $name)
    {
        $this->name = $name;
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function setWeight(int $weight)
    {
        $this->weight = $weight;
    }

    public function getWeight(): int
    {
        return $this->weight;
    }
}

Создадим класс Zoo, состоящий из разных животных и подсчитаем общий вес животных:

class Zoo
{
    protected array $animals = [];

    public function addAnimal(Animal $animal)
    {
        $this->animals[] = $animal;
    }

    public function getTotalWeight(): int
    {
        $weight = 0;
        foreach ($this->animals as $animal) {
            $weight += $animal->getWeight();
        }
        return $weight;
    }
}


// Создаем животных
$gena = new Crocodile("Gennadiy", 120);
$kesha = new Parrot("Kesha", 0.5);

// Добавляем животных в зоопарк
$zoo = new Zoo();
$zoo->addAnimal($gena);
$zoo->addAnimal($kesha);

echo "Total weight: " . $zoo->getTotalWeight(); // 120.5


Пример на Go

package main

type IAnimal interface {
   GetName() string
   GetWeight() int
}

type Parrot struct {
   name string
   weight int
}

func (p *Parrot) GetName() string {
   return p.name
}

func (p *Parrot) GetWeight() int {
   return p.weight
}

type Crocodile struct {
   name string
   weight int
}

func (p *Crocodile) GetName() string {
   return p.name
}

func (p *Crocodile) GetWeight() int {
   return p.weight
}

type Zoo struct {
   animals []IAnimal
}

func (z *Zoo) AddAnimal(animal IAnimal) {
   z.animals = append(z.animals, animal)
}

func (z *Zoo) GetTotalWeight() int {
   totalWeight := 0
   for _, v := range z.animals {
      totalWeight += v.GetWeight()
   }
   return totalWeight
}

func main() {
   gena := Crocodile{
      name:   "Gena",
      weight: 120,
   }
   
   kesha := Parrot{
      name:   "Kesha",
      weight: 1,
   }
   
   zoo := Zoo{}
   zoo.AddAnimal(&gena)
   zoo.AddAnimal(&kesha)
   zoo.GetTotalWeight() // 120.5
}


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