Skip to content

Commit 9d2f0c6

Browse files
committed
iluwatar#590 Add explanation to Decorator pattern
1 parent 6c9e005 commit 9d2f0c6

8 files changed

Lines changed: 103 additions & 173 deletions

File tree

decorator/README.md

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,96 @@ Attach additional responsibilities to an object dynamically.
1919
Decorators provide a flexible alternative to subclassing for extending
2020
functionality.
2121

22-
![alt text](./etc/decorator.png "Decorator")
22+
## Explanation
23+
24+
Real world example
25+
26+
> There is an angry troll living in the nearby hills. Usually it goes bare handed but sometimes it has a weapon. To arm the troll it's not necessary to create a new troll but to decorate it dynamically with a suitable weapon.
27+
28+
In plain words
29+
30+
> Decorator pattern lets you dynamically change the behavior of an object at run time by wrapping them in an object of a decorator class.
31+
32+
Wikipedia says
33+
34+
> In object-oriented programming, the decorator pattern is a design pattern that allows behavior to be added to an individual object, either statically or dynamically, without affecting the behavior of other objects from the same class. The decorator pattern is often useful for adhering to the Single Responsibility Principle, as it allows functionality to be divided between classes with unique areas of concern.
35+
36+
**Programmatic Example**
37+
38+
Lets take the troll example. First of all we have a simple troll implementing the troll interface
39+
40+
```
41+
public interface Troll {
42+
void attack();
43+
int getAttackPower();
44+
void fleeBattle();
45+
}
46+
47+
public class SimpleTroll implements Troll {
48+
49+
private static final Logger LOGGER = LoggerFactory.getLogger(SimpleTroll.class);
50+
51+
@Override
52+
public void attack() {
53+
LOGGER.info("The troll tries to grab you!");
54+
}
55+
56+
@Override
57+
public int getAttackPower() {
58+
return 10;
59+
}
60+
61+
@Override
62+
public void fleeBattle() {
63+
LOGGER.info("The troll shrieks in horror and runs away!");
64+
}
65+
}
66+
```
67+
68+
Next we want to add club for the troll. We can do it dynamically by using a decorator
69+
70+
```
71+
public class ClubbedTroll implements Troll {
72+
73+
private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);
74+
75+
private Troll decorated;
76+
77+
public ClubbedTroll(Troll decorated) {
78+
this.decorated = decorated;
79+
}
80+
81+
@Override
82+
public void attack() {
83+
decorated.attack();
84+
LOGGER.info("The troll swings at you with a club!");
85+
}
86+
87+
@Override
88+
public int getAttackPower() {
89+
return decorated.getAttackPower() + 10;
90+
}
91+
92+
@Override
93+
public void fleeBattle() {
94+
decorated.fleeBattle();
95+
}
96+
}
97+
```
98+
99+
Here's the troll in action
100+
101+
```
102+
// simple troll
103+
Troll troll = new SimpleTroll();
104+
troll.attack(); // The troll tries to grab you!
105+
troll.fleeBattle(); // The troll shrieks in horror and runs away!
106+
107+
// change the behavior of the simple troll by adding a decorator
108+
Troll clubbed = new ClubbedTroll(troll);
109+
clubbed.attack(); // The troll tries to grab you! The troll swings at you with a club!
110+
clubbed.fleeBattle(); // The troll shrieks in horror and runs away!
111+
```
23112

24113
## Applicability
25114
Use Decorator

decorator/etc/decorator.png

-21.3 KB
Binary file not shown.

decorator/etc/decorator.ucls

Lines changed: 0 additions & 76 deletions
This file was deleted.

decorator/etc/decorator.urm.puml

Lines changed: 0 additions & 38 deletions
This file was deleted.

decorator/src/main/java/com/iluwatar/decorator/ClubbedTroll.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,22 +28,29 @@
2828
/**
2929
* Decorator that adds a club for the troll
3030
*/
31-
public class ClubbedTroll extends TrollDecorator {
31+
public class ClubbedTroll implements Troll {
3232

3333
private static final Logger LOGGER = LoggerFactory.getLogger(ClubbedTroll.class);
3434

35+
private Troll decorated;
36+
3537
public ClubbedTroll(Troll decorated) {
36-
super(decorated);
38+
this.decorated = decorated;
3739
}
3840

3941
@Override
4042
public void attack() {
41-
super.attack();
43+
decorated.attack();
4244
LOGGER.info("The troll swings at you with a club!");
4345
}
4446

4547
@Override
4648
public int getAttackPower() {
47-
return super.getAttackPower() + 10;
49+
return decorated.getAttackPower() + 10;
50+
}
51+
52+
@Override
53+
public void fleeBattle() {
54+
decorated.fleeBattle();
4855
}
4956
}

decorator/src/main/java/com/iluwatar/decorator/TrollDecorator.java

Lines changed: 0 additions & 53 deletions
This file was deleted.

decorator/src/test/java/com/iluwatar/decorator/ClubbedTrollTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
public class ClubbedTrollTest {
3535

3636
@Test
37-
public void testSmartHostile() throws Exception {
37+
public void testClubbedTroll() throws Exception {
3838
// Create a normal troll first, but make sure we can spy on it later on.
3939
final Troll simpleTroll = spy(new SimpleTroll());
4040

pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,7 @@
469469
<param>adapter</param>
470470
<param>bridge</param>
471471
<param>composite</param>
472+
<param>decorator</param>
472473
</skipForProjects>
473474
</configuration>
474475
</plugin>

0 commit comments

Comments
 (0)