Composite Design Pattern
comes under Structural Design Pattern
.
The Composite Design Pattern is used when a class has a group of its own class, and they all share a common interface. it makes it easy to manage, add and remove further end or leaf nodes.
new functionality can be added to the common interface
which root
, intermediate
, and leaf
nodes can implement without breaking existing functionality hence following the Open/Closed Principle
.
Sometimes a group of objects is connected to each other in a hierarchical
manner, and each parent can have multiple children who have almost similar properties as the parent. It's like a tree structure
, in which there would be a root
or parent node
, an end
or leaf node
, and intermediate nodes
connecting root nodes
to leaf nodes
.
Some real-world examples of Composite Design Patterns are
An owner
of the company is a type of employee
, then under him/her, there are multiple employees
or leaf nodes
such as CEO
, CFO
, and CTO
, each leaf node
has its own further composite nodes
, such as managers
, leads
and employee
or end leaf nodes
.
A packaging box
or root
has a lot of small
or intermediate packaging box
inside which contains the actual fragile items
or leaf nodes
. Armys
or root
nodes have a hierarchical structure
. each army
consists of divisions
or intermediate nodes
, divisions
is a set of brigades
or intermediate nodes
, brigades
is a set of platoons
or intermediate nodes
, platoons
are a set of squads
or intermediate nodes
, and squads
are groups of soldiers
or leaf nodes
.
package org.wesome.design.patterns;
public interface Fruit {
void process();
}
package org.wesome.design.patterns;
import java.util.ArrayList;
import java.util.List;
public class Apple implements Fruit {
private final List<Fruit> recipeList = new ArrayList<>();
@Override
public void process() {
recipeList.forEach(System.out::println);
}
public void addRecipe(Fruit recipe) {
recipeList.add(recipe);
}
}
package org.wesome.design.patterns;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public class CrushedApple implements Fruit {
String state;
@Override
public void process() {
System.out.println("Apple can be " + state);
}
}
package org.wesome.design.patterns;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public
class Juice implements Fruit {
String state;
@Override
public void process() {
System.out.println("Juice can be made from " + state + " Apple.");
}
}
package org.wesome.design.patterns;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public
class Vine implements Fruit {
String state;
@Override
public void process() {
System.out.println("Vine can be made from " + state + " Apple.");
}
}
package org.wesome.design.patterns;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public
class CutApple implements Fruit {
String state;
@Override
public void process() {
System.out.println("Apple can be " + state + " in small pieces.");
}
}
package org.wesome.design.patterns;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
public
class Salad implements Fruit {
String state;
@Override
public void process() {
System.out.println("Salad can be made from apple " + state + " in small pieces.");
}
}
package org.wesome.design.patterns;
public class Composite {
public static void main(String[] args) {
Fruit crushed = new CrushedApple("crush");
Fruit juice = new Juice("crush");
Fruit vine = new Vine("crush");
Fruit cutInPieces = new CutApple("cut");
Fruit salad = new Salad("cut");
Apple apple = new Apple();
apple.addRecipe(crushed);
apple.addRecipe(juice);
apple.addRecipe(vine);
apple.addRecipe(cutInPieces);
apple.addRecipe(salad);
apple.process();
}
}
plugins {
id 'java'
id "io.freefair.lombok" version "6.2.0"
}
group = 'org.wesome'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = JavaVersion.VERSION_1_8
configurations {
compileOnly {
extendsFrom annotationProcessor
}
}
repositories {
mavenCentral()
}
dependencies {
implementation 'org.junit.jupiter:junit-jupiter:5.6.2'
}
test {
useJUnitPlatform()
}