Composite
Compose objects into tree structures and treat individual objects and groups uniformly.
Use it when
You model part-whole hierarchies such as menus, file systems or org charts.
// Composite
abstract class EmployeeComponent {
abstract getName(): string;
abstract getRole(): string;
abstract getSalary(): number;
private parent: EmployeeComponent | null | undefined = undefined;
public setParent(parent: EmployeeComponent | null | undefined) {
this.parent = parent;
}
public getParent(): EmployeeComponent | undefined | null {
return this.parent;
}
public isComposite(): boolean {
return false;
}
}
class Employee extends EmployeeComponent {
private name: string;
private role: string;
private salary: number;
constructor(name: string, role: string, salary: number) {
super();
this.name = name;
this.role = role;
this.salary = salary;
}
getName(): string {
return this.name;
}
getRole(): string {
return this.role;
}
getSalary(): number {
return this.salary;
}
isComposite(): boolean {
return false;
}
}
class CompositeEmployee extends EmployeeComponent {
private name: string;
private role: string = "";
private salary: number = 0;
private children: Array<EmployeeComponent> = [];
constructor(name: string, role: string, salary: number) {
super();
this.name = name;
this.role = role;
this.salary = salary;
this.children = new Array<EmployeeComponent>();
}
public getName(): string {
return this.name;
}
public getRole(): string {
return this.role;
}
public getSalary(): number {
let sal: number = 0;
for (let child of this.children) {
let cSalary: number = child.getSalary();
let p_sal: number = cSalary;
sal += p_sal;
}
if (this.isComposite()) {
sal += this.salary;
}
return sal;
}
public isComposite(): boolean {
return true;
}
public addEmployee(comp: EmployeeComponent) {
this.children.push(comp);
comp.setParent(this);
}
public removeEmployee(comp: EmployeeComponent) {
const compIndex = this.children.indexOf(comp);
this.children.splice(compIndex, 1);
comp.setParent(null);
}
public showTeam(): Array<EmployeeComponent> {
const res = this.children;
return res;
}
}
const clientCode = (comp: EmployeeComponent) => {
console.log("Result => " + comp.getName() + " " + comp.getRole());
}
const Unit1_Lead = new CompositeEmployee("P1", "lead", 60);
const dev1 = new Employee("p1-d1", "dev", 30);
const dev2 = new Employee("p1-d2", "dev", 20);
Unit1_Lead.addEmployee(dev1);
Unit1_Lead.addEmployee(dev2);
const Unit2_Lead = new CompositeEmployee("P11", "lead", 350);
const dev21 = new Employee("p11-d1", "dev", 40);
const dev22 = new Employee("p11-d2", "dev", 30);
Unit2_Lead.addEmployee(dev21);
Unit2_Lead.addEmployee(dev22);
const manager = new CompositeEmployee("top", "manager", 80)
manager.addEmployee(Unit1_Lead);
manager.addEmployee(Unit2_Lead);
clientCode(manager);
console.log("Unit1_Lead Total salary => " + Unit1_Lead.getSalary() );
console.log("Unit2_Lead Total salary => " + Unit2_Lead.getSalary() );
console.log("manager Total salary => " + manager.getSalary() );
console.log(manager.showTeam());