Skip to content

Commit 3eb27d1

Browse files
authored
Implement the Structural Design Patterns (#5)
* Implement the Adapter Design Pattern * Implement the Bridge Design Pattern * Implement the Composite Design Pattern * Implement the Decorator Design Pattern * Implement the Facade Design Pattern * Implement the Flyweight Design Pattern * Implement the Proxy Design Pattern
1 parent 017e04d commit 3eb27d1

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+857
-0
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package practice.structural.adapter;
2+
3+
/**
4+
* Example of Adapter Design Pattern
5+
*/
6+
public final class AdapterDemo {
7+
8+
public static void main(final String... arguments) {
9+
10+
new Olympian(new BoatAdapter()).rowBoat(); // Play
11+
}
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package practice.structural.adapter;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.ToString;
5+
6+
@ToString
7+
@EqualsAndHashCode
8+
public final class BoatAdapter implements RowingBoat {
9+
10+
private final FishingBoat boat = new FishingBoat();
11+
12+
@Override
13+
public void row() {
14+
boat.sail();
15+
}
16+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package practice.structural.adapter;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.extern.java.Log;
5+
6+
@Log
7+
@EqualsAndHashCode
8+
public final class FishingBoat {
9+
10+
public void sail() {
11+
log.info("Sailing BOAT => [" + this + "]");
12+
}
13+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package practice.structural.adapter;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.NonNull;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.extern.java.Log;
7+
8+
@Log
9+
@EqualsAndHashCode
10+
@RequiredArgsConstructor
11+
public final class Olympian {
12+
13+
@NonNull
14+
private final RowingBoat boat;
15+
16+
public void rowBoat() {
17+
log.info("ATHLETE in Rowing => [" + this + "]");
18+
boat.row(); // ROW currently AVAILABLE type of BOAT
19+
}
20+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package practice.structural.adapter;
2+
3+
public sealed interface RowingBoat permits BoatAdapter {
4+
5+
void row(); // Implementation of TECHNIQUES of ROWING
6+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package practice.structural.bridge;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.ToString;
5+
import lombok.extern.java.Log;
6+
7+
@Log
8+
@EqualsAndHashCode
9+
@ToString(callSuper = true)
10+
public final class BleedEffect implements Enchantment {
11+
12+
@Override
13+
public void activate() {
14+
log.info("ACTIVATED Enchantment => [" + this + "]");
15+
}
16+
17+
@Override
18+
public void apply() {
19+
log.info("APPLIED Enchantment => [" + this + "]");
20+
}
21+
22+
@Override
23+
public void deactivate() {
24+
log.info("DEACTIVATED Enchantment => [" + this + "]");
25+
}
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package practice.structural.bridge;
2+
3+
/**
4+
* Example of Bridge Design Pattern
5+
*/
6+
public final class BridgeDemo {
7+
8+
public static void main(final String... arguments) {
9+
10+
final var specialDagger = new Dagger(new PoisonEffect());
11+
12+
specialDagger.wield(); // WIELD `Dagger` with `PoisonEffect`
13+
specialDagger.use(); // USING `Dagger` with `PoisonEffect`
14+
specialDagger.sheath(); // SHEATH `Dagger` with `PoisonEffect`
15+
16+
final var specialHammer = new Hammer(new BleedEffect());
17+
18+
specialHammer.wield(); // WIELD `Hammer` with `BleedEffect`
19+
specialHammer.use(); // USING `Hammer` with `BleedEffect`
20+
specialHammer.sheath(); // SHEATH `Hammer` with `BleedEffect`
21+
}
22+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package practice.structural.bridge;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.NonNull;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.ToString;
7+
import lombok.extern.java.Log;
8+
9+
@Log
10+
@ToString
11+
@EqualsAndHashCode
12+
@RequiredArgsConstructor
13+
public final class Dagger implements Weaponry {
14+
15+
@NonNull
16+
private final Enchantment enchantment;
17+
18+
@Override
19+
public void wield() {
20+
log.info("WIELDED Weapon => [" + this + "]");
21+
enchantment.activate(); // ACTIVATE current Spell
22+
}
23+
24+
@Override
25+
public void use() {
26+
log.info("USING Weapon => [" + this + "]");
27+
enchantment.apply(); // CAST this current Spell
28+
}
29+
30+
@Override
31+
public void sheath() {
32+
log.info("SHEATHED Weapon => [" + this + "]");
33+
enchantment.deactivate(); // DEACTIVATE this Spell
34+
}
35+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package practice.structural.bridge;
2+
3+
public sealed interface Enchantment permits BleedEffect, PoisonEffect {
4+
5+
void activate(); // Abstraction of ACTIVATING Enchantment
6+
7+
void apply(); // Abstraction of APPLYING Enchantment
8+
9+
void deactivate(); // Abstraction of DEACTIVATING Enchantment
10+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package practice.structural.bridge;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.NonNull;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.ToString;
7+
import lombok.extern.java.Log;
8+
9+
@Log
10+
@ToString
11+
@EqualsAndHashCode
12+
@RequiredArgsConstructor
13+
public final class Hammer implements Weaponry {
14+
15+
@NonNull
16+
private final Enchantment enchantment;
17+
18+
@Override
19+
public void wield() {
20+
log.info("WIELDED Weapon => [" + this + "]");
21+
enchantment.activate(); // ACTIVATE current Spell
22+
}
23+
24+
@Override
25+
public void use() {
26+
log.info("USING Weapon => [" + this + "]");
27+
enchantment.apply(); // CAST this current Spell
28+
}
29+
30+
@Override
31+
public void sheath() {
32+
log.info("SHEATHED Weapon => [" + this + "]");
33+
enchantment.deactivate(); // DEACTIVATE this Spell
34+
}
35+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package practice.structural.bridge;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.ToString;
5+
import lombok.extern.java.Log;
6+
7+
@Log
8+
@EqualsAndHashCode
9+
@ToString(callSuper = true)
10+
public final class PoisonEffect implements Enchantment {
11+
12+
@Override
13+
public void activate() {
14+
log.info("ACTIVATED Enchantment => [" + this + "]");
15+
}
16+
17+
@Override
18+
public void apply() {
19+
log.info("APPLIED Enchantment => [" + this + "]");
20+
}
21+
22+
@Override
23+
public void deactivate() {
24+
log.info("DEACTIVATED Enchantment => [" + this + "]");
25+
}
26+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package practice.structural.bridge;
2+
3+
public sealed interface Weaponry permits Dagger, Hammer {
4+
5+
void wield(); // Abstraction of WIELDING Weaponry
6+
7+
void use(); // Abstraction of USING Weaponry
8+
9+
void sheath(); // Abstraction of SHEATHING Weaponry
10+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package practice.structural.composite;
2+
3+
/**
4+
* Example of Composite Design Pattern
5+
*/
6+
public final class CompositeDemo {
7+
8+
public static void main(final String... arguments) {
9+
10+
final var headDepartment1 = new HeadDepartment("HR");
11+
final var headDepartment2 = new HeadDepartment("IT");
12+
13+
final var headDepartment3 = new HeadDepartment("Company");
14+
15+
headDepartment1.addDepartment(new LeafDepartment("Relations"));
16+
headDepartment1.addDepartment(new LeafDepartment("Accounts"));
17+
18+
headDepartment2.addDepartment(new LeafDepartment("Research"));
19+
headDepartment2.addDepartment(new LeafDepartment("Testing"));
20+
21+
headDepartment3.addDepartments(headDepartment1, headDepartment2);
22+
23+
headDepartment3.printDepartmentName(); // Prints TOTAL Hierarchy
24+
}
25+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package practice.structural.composite;
2+
3+
public sealed interface Department permits HeadDepartment, LeafDepartment {
4+
5+
void printDepartmentName(); // PRINTS name of VARIOUS types of Department
6+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package practice.structural.composite;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
import lombok.EqualsAndHashCode;
6+
import lombok.NonNull;
7+
import lombok.RequiredArgsConstructor;
8+
import lombok.ToString;
9+
import lombok.extern.java.Log;
10+
11+
@Log
12+
@ToString
13+
@EqualsAndHashCode
14+
@RequiredArgsConstructor
15+
public final class HeadDepartment implements Department {
16+
17+
@ToString.Exclude
18+
private final List<Department> departments = new ArrayList<>();
19+
20+
@NonNull
21+
private final String name;
22+
23+
public void addDepartment(Department department) {
24+
departments.add(department);
25+
}
26+
27+
public void addDepartments(Department... departments) {
28+
this.departments.addAll(List.of(departments));
29+
}
30+
31+
public void removeDepartment(Department department) {
32+
departments.remove(department);
33+
}
34+
35+
@Override
36+
public void printDepartmentName() {
37+
log.info("NAME of Department => [" + this + "]");
38+
departments.forEach(Department::printDepartmentName);
39+
}
40+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package practice.structural.composite;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.NonNull;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.ToString;
7+
import lombok.extern.java.Log;
8+
9+
@Log
10+
@ToString
11+
@EqualsAndHashCode
12+
@RequiredArgsConstructor
13+
public final class LeafDepartment implements Department {
14+
15+
@NonNull
16+
private final String name;
17+
18+
@Override
19+
public void printDepartmentName() {
20+
log.info("NAME of Department => [" + this + "]");
21+
}
22+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package practice.structural.decorator;
2+
3+
import lombok.EqualsAndHashCode;
4+
import lombok.NonNull;
5+
import lombok.ToString;
6+
7+
@ToString(callSuper = true)
8+
@EqualsAndHashCode(callSuper = true)
9+
public final class ChickenTaco extends TacoDecorator {
10+
11+
private static final Float MULTIPLIER = 1.35F;
12+
13+
public ChickenTaco(@NonNull final TacoRecipe taco) {
14+
super(taco);
15+
}
16+
17+
@Override
18+
public float getCost() {
19+
return taco.getCost() * MULTIPLIER;
20+
}
21+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package practice.structural.decorator;
2+
3+
/**
4+
* Example of Decorator Design Pattern
5+
*/
6+
public final class DecoratorDemo {
7+
8+
public static void main(final String... arguments) {
9+
10+
final var plainTaco = new PlainTaco();
11+
plainTaco.printCost(); // Cook PLAIN
12+
13+
final var friedTaco = new FriedTaco(plainTaco);
14+
friedTaco.printCost(); // Decorate FRIED Taco
15+
16+
final var chickenTaco = new ChickenTaco(friedTaco);
17+
chickenTaco.printCost(); // Decorate CHICKEN Taco
18+
}
19+
}

0 commit comments

Comments
 (0)