Паттерн Композит относится к структурным паттернам проектирования, в отечественных источниках он известен как “Компоновщик”.
Допустим мы разрабатываем приложение – фотоальбом. Пользователь может создавать папки, добавлять туда фото, производить прочие манипуляции. Обязательно нужна возможность показывать количество файлов в папках, общее количество всех файлов и папок.
Очевидно что нужно использовать дерево, но как реализовать архитектуру древа, с простым и удобным интерфейсом? На помощь приходит паттерн Композит.
Реализуем интерфейс Component с нужным нам методом dataCount(), через него будем возвращать количество файлов/директорий. Создадим класс Directory, с интерфейсом позволяющим добавлять/удалять экземпляры классов реализующие интерфейс Component, по схеме паттерна это Composite. Также создадим класс File, там храним байты с фотокарточкой, наследуем от Component, через dataCount возвращаем 1, мол фото одно!
Далее в Directory реализуем метод dataCount() – путем прохода по всем элементам лежащим в массиве компонентов, сложив все их dataCount’s.
Все готово!
Ниже пример на Go:
package main
import "fmt"
type component interface {
dataCount() int
}
type file struct {
}
type directory struct {
c []component
}
func (f file) dataCount() int {
return 1
}
func (d directory) dataCount() int {
var outputDataCount int = 0
for _, v := range d.c {
outputDataCount += v.dataCount()
}
return outputDataCount
}
func (d *directory) addComponent(c component) {
d.c = append(d.c, c)
}
func main() {
var f file
var rd directory
rd.addComponent(f)
rd.addComponent(f)
rd.addComponent(f)
rd.addComponent(f)
fmt.Println(rd.dataCount())
var sd directory
sd.addComponent(f)
rd.addComponent(sd)
rd.addComponent(sd)
rd.addComponent(sd)
fmt.Println(sd.dataCount())
fmt.Println(rd.dataCount())
}
Источники
https://refactoring.guru/ru/design-patterns/composite