[JS ES6 Паттерн КОМПОНОВЩИК (composite)] #Паттерны #ООП #ES6 #js
/**
*
* ПАТТЕРН КОМПОНОВЩИК (composite)
*
* Шаблон Компоновщик позволяет единообразно обрабатывать отдельные объекты и их группы. Он работает с иерархией «часть-целое».
* Паттерн Компоновщик позволяет создавать древовидные структуры, узлами которых являются как комбинации, так и
* отдельные объекты.
* ВАЖНО: в такой структуре одни и те же операции могут применяться и к комбинациям, и к отдельным объектам.
*
* Клиент работает с деревом через общий интерфейс компонентов (interface Component).
* Благодаря этому, клиенту не важно, что перед ним находится — простой или составной компонент дерева.
*/
class Component { // общий интерфейс для всех элементов системы
static countElems = 0; // считает количество добавленных элементов. Номер добавленного элемента записываетс как его id
constructor() {
this.parentsNum = 0; // количество родителей элемента (уровень вложенности)
this.elemPrefix = ''; // (определяет количество отступов при выводе элементов)
this.elemsList = []; // хранится результат GetElemList()
this.id = Component.countElems; // присваиваем данному элеенту при создании его id
Component.countElems++;
}
ShowHierarchy (){ // выводит иерархию всех элементов Компоновщика
this.elemPrefix = this.setPrefixLength(this.parentsNum);
}
Add (Component){ // добавляет элементы в компановщик
throw new Error(`В ${this.constructor.name} не описан метод Add()`);
}
Remove (Component){
throw new Error(`В ${this.constructor.name} не описан метод Remove()`);
}
GetChild (key){
return this.children[key]
}
GetAllChildren (){ // Выводит массив всех элементов компановщика без иерархии.
// Соответственно можно обрабатывать скопом данные из всех элементов
throw new Error(`В ${this.constructor.name} не описан метод GetAllChildren()`);
}
GetChildrenByParentId() {
throw new Error(`В ${this.constructor.name} не описан метод GetChildrenByParentId()`);
}
setPrefixLength(count) { //функция определяет длину префикса elemPrefix выводимого в ShowHierarchy()
let pre = '';
for (let i = 0; i < count; i++) {
pre += '----';
}
return pre;
}
}
class Leaf extends Component { // одиночный элементо системы (не может иметь потомков)
constructor(name) {
super();
this.name = name
console.log('Leaf created')
}
ShowHierarchy (){
super.ShowHierarchy();
console.log(this.elemPrefix+this.name)
}
}
class Composite extends Component { // сборный элемент системы. Может включать в себя другие Leaf или Composite.
constructor(name) {
super();
this.name = name
this.children = []
console.log('Composite created')
}
ShowHierarchy (){
super.ShowHierarchy();
console.log(this.elemPrefix+this.name + ' (Composite)')
for(var i in this.children)
this.children[i].ShowHierarchy()
}
Add (elem){
elem.parentsNum = this.parentsNum +1;
elem.parentId = this.id; // присваиваем добавляемому элементу parentId в виде id эл-та в который идет добавление
this.children.push(elem)
}
Remove (elem){
for(var i in this.children)
if(this.children[i] === elem)
this.children.splice(i, 1)
}
GetChild (key){
return this.children[key]
}
GetAllChildren (childrenArr){ // возвращает массив элементов, включая вложенные элементы.
if (!childrenArr) { // обнуляем массив при НЕрекурсивном вызове метода, иначе данные копятся
this.elemsList = [];
childrenArr = this.children;
}
for(var i in childrenArr) {
this.elemsList.push(childrenArr[i]/*.name*/);
if (childrenArr[i].children) { // если есть потомки, то для них рекурсивно вызываем этот же метод
this.GetAllChildren(childrenArr[i].children)
}
}
return this.elemsList;
}
GetChildrenByParentId(parentId) {
this.GetAllChildren();
const arrLength = this.elemsList.length;
for (let i = 0; i < arrLength; i++) {
if (this.elemsList[i].id == parentId) {
console.log(this.elemsList[i].GetAllChildren());
}
}
}
}
var animal = new Composite('Животные')
animal.Add(new Leaf('Рыбы'))
animal.Add(new Leaf('Птицы'))
var mammals = new Composite('Млекопитающие')
animal.Add(mammals)
mammals.Add(new Leaf('Медведи'))
var dogs = new Composite('Собаки')
mammals.Add(dogs)
dogs.Add(new Leaf('Крупные'))
dogs.Add(new Leaf('Карликовые'))
mammals.Add(new Leaf('Киты'))
var plants = new Composite('Растения')
animal.Add(plants)
plants.Add(new Leaf('Дуб'))
plants.Add(new Leaf('Береза'))
plants.Add(new Leaf('Сосна'))
animal.ShowHierarchy()
let elemList = animal.GetAllChildren();
console.log(elemList);
animal.GetChild(1).ShowHierarchy()
function findElemById (arr, id) { // функция находит в массиве elemList элемент по id
const arrLength = arr.length;
for (let i = 0; i < arrLength; i++) {
if (arr[i].id == id) {
console.log(`Найден элемент с id ${id}: ${arr[i].name}`);
}
}
}
findElemById(elemList, animal.children[2].children[0].parentId);