Skip to content

Commit 0c31312

Browse files
committed
docs: update crtp
1 parent 9890579 commit 0c31312

File tree

5 files changed

+39
-63
lines changed

5 files changed

+39
-63
lines changed

curiously-recurring-template-pattern/README.md

Lines changed: 39 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,13 @@ title: Curiously Recurring Template Pattern
33
language: en
44
category: Structural
55
tag:
6+
- Code simplification
67
- Extensibility
8+
- Generic
79
- Idiom
810
- Instantiation
11+
- Polymorphism
12+
- Recursion
913
---
1014

1115
## Also known as
@@ -24,7 +28,11 @@ Curiously Recurring Template Pattern (CRTP) is used to achieve a form of static
2428

2529
Real-world example
2630

27-
> For a mixed martial arts promotion that is planning an event, ensuring that the fights are organized between athletes of the same weight class is crucial. This prevents mismatches between fighters of significantly different sizes, such as a heavyweight facing off against a bantamweight.
31+
> Consider a scenario where a library system manages various types of media: books, DVDs, and magazines. Each media type has specific attributes and behaviors, but they all share common functionality like borrowing and returning.
32+
>
33+
> Using the Curiously Recurring Template Pattern (CRTP), you can create a base template class `MediaItem` that includes these common methods. Each specific media type (e.g., `Book`, `DVD`, `Magazine`) would then inherit from `MediaItem` using itself as a template parameter. This allows each media type to customize the common functionality without the overhead of virtual methods.
34+
>
35+
> For example, `Book` would inherit from `MediaItem<Book>`, allowing the library system to use polymorphic behavior at compile-time, ensuring that each media type implements the necessary methods efficiently. This approach provides the benefits of polymorphism and code reuse while maintaining high performance and type safety.
2836
2937
In plain words
3038

@@ -36,7 +44,9 @@ Wikipedia says
3644
3745
**Programmatic example**
3846

39-
Let's define the generic interface Fighter.
47+
For a mixed martial arts promotion that is planning an event, ensuring that the fights are organized between athletes of the same weight class is crucial. This prevents mismatches between fighters of significantly different sizes, such as a heavyweight facing off against a bantamweight.
48+
49+
Let's define the generic interface `Fighter`.
4050

4151
```java
4252
public interface Fighter<T> {
@@ -46,93 +56,64 @@ public interface Fighter<T> {
4656
}
4757
```
4858

49-
The MMAFighter class is used to instantiate fighters distinguished by their weight class.
59+
The `MMAFighter` class is used to instantiate fighters distinguished by their weight class.
5060

5161
```java
62+
@Slf4j
63+
@Data
5264
public class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {
5365

54-
private final String
55-
name;
56-
private final String
57-
surname;
58-
private final String
59-
nickName;
60-
private final String
61-
speciality;
62-
63-
public MmaFighter(
64-
String name,
65-
String surname,
66-
String nickName,
67-
String speciality) {
68-
this.name =
69-
name;
70-
this.surname =
71-
surname;
72-
this.nickName =
73-
nickName;
74-
this.speciality =
75-
speciality;
76-
}
77-
78-
@Override
79-
public void fight(
80-
T opponent) {
81-
LOGGER.info(
82-
"{} is going to fight against {}",
83-
this,
84-
opponent);
85-
}
66+
private final String name;
67+
private final String surname;
68+
private final String nickName;
69+
private final String speciality;
8670

8771
@Override
88-
public String toString() {
89-
return
90-
name +
91-
" \"" +
92-
nickName +
93-
"\" " +
94-
surname;
72+
public void fight(T opponent) {
73+
LOGGER.info("{} is going to fight against {}", this, opponent);
9574
}
9675
}
9776
```
9877

99-
The followings are some subtypes of MmaFighter.
78+
The followings are some subtypes of `MmaFighter`.
10079

10180
```java
10281
class MmaBantamweightFighter extends MmaFighter<MmaBantamweightFighter> {
10382

10483
public MmaBantamweightFighter(String name, String surname, String nickName, String speciality) {
10584
super(name, surname, nickName, speciality);
10685
}
107-
10886
}
10987

11088
public class MmaHeavyweightFighter extends MmaFighter<MmaHeavyweightFighter> {
11189

11290
public MmaHeavyweightFighter(String name, String surname, String nickName, String speciality) {
11391
super(name, surname, nickName, speciality);
11492
}
115-
11693
}
11794
```
11895

11996
A fighter is allowed to fight an opponent of the same weight classes. If the opponent is of a different weight class, an error is raised.
12097

12198
```java
122-
MmaBantamweightFighter fighter1=new MmaBantamweightFighter("Joe","Johnson","The Geek","Muay Thai");
123-
MmaBantamweightFighter fighter2=new MmaBantamweightFighter("Ed","Edwards","The Problem Solver","Judo");
124-
fighter1.fight(fighter2); // This is fine
99+
public static void main(String[] args) {
125100

126-
MmaHeavyweightFighter fighter3=new MmaHeavyweightFighter("Dave","Davidson","The Bug Smasher","Kickboxing");
127-
MmaHeavyweightFighter fighter4=new MmaHeavyweightFighter("Jack","Jackson","The Pragmatic","Brazilian Jiu-Jitsu");
128-
fighter3.fight(fighter4); // This is fine too
101+
MmaBantamweightFighter fighter1 = new MmaBantamweightFighter("Joe", "Johnson", "The Geek", "Muay Thai");
102+
MmaBantamweightFighter fighter2 = new MmaBantamweightFighter("Ed", "Edwards", "The Problem Solver", "Judo");
103+
fighter1.fight(fighter2);
129104

130-
fighter1.fight(fighter3); // This will raise a compilation error
105+
MmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter("Dave", "Davidson", "The Bug Smasher", "Kickboxing");
106+
MmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter("Jack", "Jackson", "The Pragmatic", "Brazilian Jiu-Jitsu");
107+
fighter3.fight(fighter4);
108+
}
131109
```
132110

133-
## Class diagram
111+
Program output:
134112

135-
![alt text](./etc/crtp.png "CRTP class diagram")
113+
```
114+
08:42:34.048 [main] INFO crtp.MmaFighter -- MmaFighter(name=Joe, surname=Johnson, nickName=The Geek, speciality=Muay Thai) is going to fight against MmaFighter(name=Ed, surname=Edwards, nickName=The Problem Solver, speciality=Judo)
115+
08:42:34.054 [main] INFO crtp.MmaFighter -- MmaFighter(name=Dave, surname=Davidson, nickName=The Bug Smasher, speciality=Kickboxing) is going to fight against MmaFighter(name=Jack, surname=Jackson, nickName=The Pragmatic, speciality=Brazilian Jiu-Jitsu)
116+
```
136117

137118
## Applicability
138119

@@ -145,14 +126,13 @@ MmaBantamweightFighter fighter1=new MmaBantamweightFighter("Joe","Johnson","The
145126

146127
## Tutorials
147128

148-
* [The NuaH Blog](https://nuah.livejournal.com/328187.html)
149-
* Yogesh Umesh Vaity's answer to [What does "Recursive type bound" in Generics mean?](https://stackoverflow.com/questions/7385949/what-does-recursive-type-bound-in-generics-mean)
129+
* [Curiously Recurring Template Pattern in Java (The NuaH Blog)](https://nuah.livejournal.com/328187.html)
150130

151131
## Known uses
152132

153133
* Implementing compile-time polymorphic interfaces in template libraries.
154134
* Enhancing code reuse in libraries where performance is critical, like in mathematical computations, embedded systems, and real-time processing applications.
155-
* [java.lang.Enum](https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Enum.html)
135+
* Implementation of the `Cloneable` interface in various Java libraries.
156136

157137
## Consequences
158138

@@ -176,5 +156,5 @@ Trade-offs:
176156

177157
## Credits
178158

179-
* [Effective Java](https://www.amazon.com/gp/product/0134685997/ref=as_li_tl?ie=UTF8&camp=1789&creative=9325&creativeASIN=0134685997&linkCode=as2&tag=javadesignpat-20&linkId=4e349f4b3ff8c50123f8147c828e53eb)
180-
* [How do I decrypt "Enum<E extends Enum\<E>>"?](http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeParameters.html#FAQ106)
159+
* [Design Patterns: Elements of Reusable Object-Oriented Software](https://amzn.to/3w0pvKI)
160+
* [Effective Java](https://amzn.to/4cGk2Jz)
Binary file not shown.

curiously-recurring-template-pattern/etc/crtp.urm.puml

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

curiously-recurring-template-pattern/src/main/java/crtp/App.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,5 @@ public static void main(String[] args) {
4747
MmaHeavyweightFighter fighter3 = new MmaHeavyweightFighter("Dave", "Davidson", "The Bug Smasher", "Kickboxing");
4848
MmaHeavyweightFighter fighter4 = new MmaHeavyweightFighter("Jack", "Jackson", "The Pragmatic", "Brazilian Jiu-Jitsu");
4949
fighter3.fight(fighter4);
50-
5150
}
5251
}

curiously-recurring-template-pattern/src/main/java/crtp/MmaFighter.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,4 @@ public class MmaFighter<T extends MmaFighter<T>> implements Fighter<T> {
4545
public void fight(T opponent) {
4646
LOGGER.info("{} is going to fight against {}", this, opponent);
4747
}
48-
4948
}

0 commit comments

Comments
 (0)