Last active
April 25, 2024 15:23
-
-
Save DmitriiNazimov/b70a24695234e3ab9567f57e0632f51c to your computer and use it in GitHub Desktop.
[JS ES6 Паттерн КОМПОНОВЩИК (composite)] #Паттерны #ООП #ES6 #js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* ПАТТЕРН КОМПОНОВЩИК (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); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Уыцфт