Skip to content

Commit d6bb988

Browse files
committed
docs: update extension objects
1 parent b901e51 commit d6bb988

File tree

1 file changed

+73
-68
lines changed

1 file changed

+73
-68
lines changed

extension-objects/README.md

Lines changed: 73 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The Extension Objects pattern allows for the flexible extension of an object's b
2121

2222
Real-world example
2323

24-
> Suppose you are developing a Java-based game for a client, and in the middle of the development process, new features are suggested. The Extension Objects pattern empowers your program to adapt to unforeseen changes with minimal refactoring, especially when integrating additional functionalities into your project.
24+
> An analogous real-world example of the Extension Objects design pattern can be found in modular kitchen appliances. Consider a base blender unit to which different attachments can be added, such as a food processor, juicer, or grinder. Each attachment adds new functionality to the blender without altering the base unit itself. Users can dynamically switch between different functionalities based on their current needs, making the blender highly versatile and adaptable to various tasks. This mirrors the Extension Objects pattern in software, where new functionalities are added to an object dynamically and contextually, enhancing flexibility and reuse.
2525
2626
In plain words
2727

@@ -33,108 +33,113 @@ Wikipedia says
3333
3434
**Programmatic example**
3535

36-
The aim of utilising the Extension Objects pattern is to implement new features/functionality without having to refactor every class. The following examples shows utilising this pattern for an Enemy class extending Entity within a game:
36+
The Extension Objects pattern allows for the flexible extension of an object's behavior without modifying its structure, by attaching additional objects that can dynamically add new functionality.
37+
38+
In this example, we have three types of units: `SoldierUnit`, `SergeantUnit`, and `CommanderUnit`. Each unit can have extensions that provide additional functionality. The extensions are `SoldierExtension`, `SergeantExtension`, and `CommanderExtension`.
3739

38-
Primary App class to execute our program from.
40+
The `Unit` class is the base class for all units. It has a method `getUnitExtension` that returns an extension object based on the extension name.
3941

4042
```java
41-
public class App {
42-
public static void main(String[] args) {
43-
Entity enemy = new Enemy("Enemy");
44-
checkExtensionsForEntity(enemy);
45-
}
43+
public abstract class Unit {
44+
private String name;
4645

47-
private static void checkExtensionsForEntity(Entity entity) {
48-
Logger logger = Logger.getLogger(App.class.getName());
49-
String name = entity.getName();
50-
Function<String, Runnable> func = (e) -> () -> logger.info(name + " without " + e);
46+
protected Unit(String name) {
47+
this.name = name;
48+
}
5149

52-
String extension = "EnemyExtension";
53-
Optional.ofNullable(entity.getEntityExtension(extension))
54-
.map(e -> (EnemyExtension) e)
55-
.ifPresentOrElse(EnemyExtension::extendedAction, func.apply(extension));
56-
}
50+
public String getName() {
51+
return name;
52+
}
53+
54+
public abstract UnitExtension getUnitExtension(String extensionName);
5755
}
5856
```
5957

60-
Enemy class with initial actions and extensions.
58+
The `UnitExtension` interface is the base interface for all extensions. Each specific extension will implement this interface.
6159

6260
```java
63-
class Enemy extends Entity {
64-
public Enemy(String name) {
65-
super(name);
66-
}
67-
68-
@Override
69-
protected void performInitialAction() {
70-
super.performInitialAction();
71-
System.out.println("Enemy wants to attack you.");
72-
}
73-
74-
@Override
75-
public EntityExtension getEntityExtension(String extensionName) {
76-
if (extensionName.equals("EnemyExtension")) {
77-
return Optional.ofNullable(entityExtension).orElseGet(EnemyExtension::new);
78-
}
79-
return super.getEntityExtension(extensionName);
80-
}
61+
public interface UnitExtension {
62+
String getName();
8163
}
8264
```
8365

84-
EnemyExtension class with overriding extendAction() method.
66+
The `SoldierUnit` class is a specific type of unit. It overrides the `getUnitExtension` method to return a `SoldierExtension` object.
8567

8668
```java
87-
class EnemyExtension implements EntityExtension {
88-
@Override
89-
public void extendedAction() {
90-
System.out.println("Enemy has advanced towards you!");
69+
public class SoldierUnit extends Unit {
70+
public SoldierUnit(String name) {
71+
super(name);
72+
}
73+
74+
@Override
75+
public UnitExtension getUnitExtension(String extensionName) {
76+
if ("SoldierExtension".equals(extensionName)) {
77+
return new SoldierExtension(this);
9178
}
79+
return null;
80+
}
9281
}
9382
```
9483

95-
Entity class which will be extended by Enemy.
84+
The `SoldierExtension` class is a specific type of extension. It implements the `UnitExtension` interface and provides additional functionality for the `SoldierUnit`.
9685

9786
```java
98-
class Entity {
99-
private String name;
100-
protected EntityExtension entityExtension;
87+
public class SoldierExtension implements UnitExtension {
88+
private SoldierUnit unit;
10189

102-
public Entity(String name) {
103-
this.name = name;
104-
performInitialAction();
105-
}
90+
public SoldierExtension(SoldierUnit unit) {
91+
this.unit = unit;
92+
}
10693

107-
protected void performInitialAction() {
108-
System.out.println(name + " performs the initial action.");
109-
}
94+
@Override
95+
public String getName() {
96+
return "SoldierExtension";
97+
}
11098

111-
public EntityExtension getEntityExtension(String extensionName) {
112-
return null;
113-
}
114-
115-
public String getName() {
116-
return name;
117-
}
99+
public void soldierReady() {
100+
// additional functionality for SoldierUnit
101+
}
118102
}
119103
```
120104

121-
EntityExtension interface to be used by EnemyExtension.
105+
In the `main` application, we create different types of units and check for each unit to have an extension. If the extension exists, we call the specific method on the extension object.
122106

123107
```java
124-
interface EntityExtension {
125-
void extendedAction();
108+
public class App {
109+
public static void main(String[] args) {
110+
var soldierUnit = new SoldierUnit("SoldierUnit1");
111+
var sergeantUnit = new SergeantUnit("SergeantUnit1");
112+
var commanderUnit = new CommanderUnit("CommanderUnit1");
113+
114+
checkExtensionsForUnit(soldierUnit);
115+
checkExtensionsForUnit(sergeantUnit);
116+
checkExtensionsForUnit(commanderUnit);
117+
}
118+
119+
private static void checkExtensionsForUnit(Unit unit) {
120+
var extension = "SoldierExtension";
121+
Optional.ofNullable(unit.getUnitExtension(extension))
122+
.map(e -> (SoldierExtension) e)
123+
.ifPresentOrElse(SoldierExtension::soldierReady, () -> System.out.println(unit.getName() + " without " + extension));
124+
}
126125
}
127126
```
128127

129-
Program output:
128+
This produces the following console output.
130129

131-
```markdown
132-
Enemy performs the initial action.
133-
Enemy wants to attack you.
134-
Enemy has advanced towards you!
130+
```
131+
22:58:03.779 [main] INFO concreteextensions.Soldier -- [Soldier] SoldierUnit1 is ready!
132+
22:58:03.781 [main] INFO App -- SoldierUnit1 without SergeantExtension
133+
22:58:03.782 [main] INFO App -- SoldierUnit1 without CommanderExtension
134+
22:58:03.782 [main] INFO App -- SergeantUnit1 without SoldierExtension
135+
22:58:03.783 [main] INFO concreteextensions.Sergeant -- [Sergeant] SergeantUnit1 is ready!
136+
22:58:03.783 [main] INFO App -- SergeantUnit1 without CommanderExtension
137+
22:58:03.783 [main] INFO App -- CommanderUnit1 without SoldierExtension
138+
22:58:03.783 [main] INFO App -- CommanderUnit1 without SergeantExtension
139+
22:58:03.783 [main] INFO concreteextensions.Commander -- [Commander] CommanderUnit1 is ready!
135140
```
136141

137-
In this example, the Extension Objects pattern allows the enemy entity to perform unique initial actions and advanced actions when specific extensions are applied. This pattern provides flexibility and extensibility to the codebase while minimizing the need for major code changes.
142+
This example demonstrates how the Extension Objects pattern allows for the flexible extension of an object's behavior without modifying its structure.
138143

139144
## Class diagram
140145

0 commit comments

Comments
 (0)